Merge branch 'drivers/pxa-gpio' into next/drivers
authorArnd Bergmann <arnd@arndb.de>
Thu, 8 Dec 2011 16:13:36 +0000 (16:13 +0000)
committerArnd Bergmann <arnd@arndb.de>
Thu, 8 Dec 2011 16:13:36 +0000 (16:13 +0000)
1329 files changed:
.mailmap
Documentation/ABI/stable/sysfs-acpi-pmprofile [new file with mode: 0644]
Documentation/ABI/testing/sysfs-block
Documentation/DocBook/drm.tmpl
Documentation/DocBook/mtdnand.tmpl
Documentation/DocBook/uio-howto.tmpl
Documentation/blockdev/cciss.txt
Documentation/cgroups/freezer-subsystem.txt
Documentation/devicetree/bindings/mtd/atmel-dataflash.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/filesystems/btrfs.txt
Documentation/i2c/ten-bit-addresses
Documentation/networking/ip-sysctl.txt
Documentation/power/devices.txt
Documentation/power/runtime_pm.txt
Documentation/serial/serial-rs485.txt
Documentation/sound/alsa/HD-Audio-Models.txt
Documentation/sound/alsa/HD-Audio.txt
Kbuild
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/boot/Makefile
arch/arm/boot/dts/tegra-ventana.dts
arch/arm/common/gic.c
arch/arm/common/pl330.c
arch/arm/configs/at91cap9_defconfig [new file with mode: 0644]
arch/arm/configs/at91cap9adk_defconfig [deleted file]
arch/arm/configs/at91rm9200_defconfig
arch/arm/configs/at91sam9260_defconfig [new file with mode: 0644]
arch/arm/configs/at91sam9260ek_defconfig [deleted file]
arch/arm/configs/at91sam9g20_defconfig [new file with mode: 0644]
arch/arm/configs/at91sam9g20ek_defconfig [deleted file]
arch/arm/configs/at91sam9g45_defconfig
arch/arm/configs/at91sam9rl_defconfig [new file with mode: 0644]
arch/arm/configs/at91sam9rlek_defconfig [deleted file]
arch/arm/configs/ezx_defconfig
arch/arm/configs/imote2_defconfig
arch/arm/configs/magician_defconfig
arch/arm/configs/omap1_defconfig
arch/arm/configs/u300_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/configs/zeus_defconfig
arch/arm/include/asm/hardware/cache-l2x0.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/pmu.h
arch/arm/include/asm/topology.h
arch/arm/include/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kernel/entry-armv.S
arch/arm/kernel/head.S
arch/arm/kernel/kprobes-arm.c
arch/arm/kernel/kprobes-test-arm.c
arch/arm/kernel/kprobes-test-thumb.c
arch/arm/kernel/kprobes-test.h
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/pmu.c
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/kernel/topology.c
arch/arm/lib/bitops.h
arch/arm/lib/changebit.S
arch/arm/lib/clearbit.S
arch/arm/lib/setbit.S
arch/arm/lib/testchangebit.S
arch/arm/lib/testclearbit.S
arch/arm/lib/testsetbit.S
arch/arm/mach-at91/at91cap9.c
arch/arm/mach-at91/at91cap9_devices.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/board-1arm.c
arch/arm/mach-at91/board-afeb-9260v1.c
arch/arm/mach-at91/board-cam60.c
arch/arm/mach-at91/board-cap9adk.c
arch/arm/mach-at91/board-carmeva.c
arch/arm/mach-at91/board-cpu9krea.c
arch/arm/mach-at91/board-cpuat91.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-csb637.c
arch/arm/mach-at91/board-eb9200.c
arch/arm/mach-at91/board-ecbat91.c
arch/arm/mach-at91/board-eco920.c
arch/arm/mach-at91/board-foxg20.c
arch/arm/mach-at91/board-gsia18s.c
arch/arm/mach-at91/board-kafa.c
arch/arm/mach-at91/board-kb9202.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-picotux200.c
arch/arm/mach-at91/board-qil-a9260.c
arch/arm/mach-at91/board-rm9200dk.c
arch/arm/mach-at91/board-rm9200ek.c
arch/arm/mach-at91/board-rsi-ews.c
arch/arm/mach-at91/board-sam9-l9260.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/board-snapper9260.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/board-usb-a926x.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/cpuidle.c
arch/arm/mach-at91/include/mach/board.h
arch/arm/mach-at91/include/mach/vmalloc.h
arch/arm/mach-bcmring/core.c
arch/arm/mach-bcmring/dma.c
arch/arm/mach-davinci/board-da830-evm.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm355-evm.c
arch/arm/mach-davinci/board-dm355-leopard.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-mityomapl138.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/board-tnetv107x-evm.c
arch/arm/mach-davinci/cpuidle.c
arch/arm/mach-davinci/include/mach/nand.h
arch/arm/mach-ep93xx/ts72xx.c
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile.boot
arch/arm/mach-imx/clock-imx6q.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-imx/src.c
arch/arm/mach-kirkwood/cpuidle.c
arch/arm/mach-mmp/aspenite.c
arch/arm/mach-mmp/gplugd.c
arch/arm/mach-mmp/include/mach/gpio-pxa.h
arch/arm/mach-msm/Makefile
arch/arm/mach-msm/board-msm7x30.c
arch/arm/mach-msm/board-msm8960.c
arch/arm/mach-msm/board-msm8x60.c
arch/arm/mach-msm/scm.c
arch/arm/mach-mx5/clock-mx51-mx53.c
arch/arm/mach-mx5/cpu.c
arch/arm/mach-mx5/mm.c
arch/arm/mach-mxs/clock-mx28.c
arch/arm/mach-mxs/devices-mx28.h
arch/arm/mach-mxs/devices/platform-mxs-saif.c
arch/arm/mach-mxs/include/mach/common.h
arch/arm/mach-mxs/include/mach/devices-common.h
arch/arm/mach-mxs/include/mach/digctl.h [new file with mode: 0644]
arch/arm/mach-mxs/mach-mx28evk.c
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/board-palmz71.c
arch/arm/mach-omap1/clock.h
arch/arm/mach-omap1/clock_data.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/pm.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/clkt_dpll.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock2420_data.c
arch/arm/mach-omap2/clock2430_data.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx.h
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/display.h [new file with mode: 0644]
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/dpll44xx.c
arch/arm/mach-omap2/dsp.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/io.h [deleted file]
arch/arm/mach-omap2/mailbox.c
arch/arm/mach-omap2/omap-iommu.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_common_data.c
arch/arm/mach-omap2/omap_hwmod_common_data.h
arch/arm/mach-omap2/omap_l3_noc.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/powerdomain.h
arch/arm/mach-omap2/smartreflex.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/twl-common.h
arch/arm/mach-omap2/usb-musb.c
arch/arm/mach-orion5x/ts78xx-setup.c
arch/arm/mach-picoxcell/include/mach/debug-macro.S
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/colibri-pxa3xx.c
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/include/mach/palm27x.h
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/mxm8x10.c
arch/arm/mach-pxa/palm27x.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-shmobile/Makefile
arch/arm/mach-shmobile/board-ag5evm.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-kota2.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/cpuidle.c
arch/arm/mach-shmobile/include/mach/common.h
arch/arm/mach-shmobile/include/mach/sh73a0.h
arch/arm/mach-shmobile/pfc-sh7367.c
arch/arm/mach-shmobile/pfc-sh7372.c
arch/arm/mach-shmobile/pfc-sh7377.c
arch/arm/mach-shmobile/pfc-sh73a0.c
arch/arm/mach-shmobile/pm-sh7372.c
arch/arm/mach-shmobile/pm_runtime.c [deleted file]
arch/arm/mach-tegra/board-dt.c
arch/arm/mach-tegra/board-harmony-pinmux.c
arch/arm/mach-tegra/board-paz00-pinmux.c
arch/arm/mach-tegra/board-seaboard-pinmux.c
arch/arm/mach-tegra/board-trimslice-pinmux.c
arch/arm/mach-w90x900/dev.c
arch/arm/mach-w90x900/include/mach/mfp.h
arch/arm/mach-w90x900/include/mach/nuc900_spi.h
arch/arm/mach-w90x900/mfp.c
arch/arm/mm/cache-l2x0.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mmap.c
arch/arm/plat-mxc/Kconfig
arch/arm/plat-mxc/avic.c
arch/arm/plat-mxc/gic.c
arch/arm/plat-mxc/include/mach/common.h
arch/arm/plat-mxc/include/mach/entry-macro.S
arch/arm/plat-mxc/include/mach/mxc.h
arch/arm/plat-mxc/include/mach/system.h
arch/arm/plat-mxc/system.c
arch/arm/plat-mxc/tzic.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/i2c.c
arch/arm/plat-omap/include/plat/clock.h
arch/arm/plat-omap/include/plat/common.h
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/plat-omap/include/plat/omap-alsa.h [deleted file]
arch/arm/plat-omap/include/plat/omap-pm.h
arch/arm/plat-omap/include/plat/omap_device.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/omap-pm-noop.c
arch/arm/plat-omap/omap_device.c
arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
arch/arm/plat-s3c24xx/cpu-freq-debugfs.c
arch/arm/plat-s5p/sysmmu.c
arch/arm/plat-samsung/dma-ops.c
arch/arm/plat-samsung/include/plat/gpio-cfg.h
arch/arm/plat-samsung/pd.c
arch/arm/plat-samsung/pwm.c
arch/arm/plat-samsung/s3c-dma-ops.c
arch/arm/tools/mach-types
arch/avr32/boards/atngw100/setup.c
arch/avr32/boards/atstk1000/atstk1002.c
arch/avr32/boards/favr-32/setup.c
arch/avr32/boards/hammerhead/setup.c
arch/avr32/boards/merisc/setup.c
arch/avr32/boards/mimc200/setup.c
arch/avr32/mach-at32ap/at32ap700x.c
arch/avr32/mach-at32ap/include/mach/board.h
arch/blackfin/include/asm/bfin_serial.h
arch/blackfin/mach-bf518/boards/ezbrd.c
arch/blackfin/mach-bf518/boards/tcm-bf518.c
arch/blackfin/mach-bf527/boards/ad7160eval.c
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/boards/tll6527m.c
arch/blackfin/mach-bf533/boards/H8606.c
arch/blackfin/mach-bf533/boards/blackstamp.c
arch/blackfin/mach-bf533/boards/cm_bf533.c
arch/blackfin/mach-bf533/boards/ezkit.c
arch/blackfin/mach-bf533/boards/ip0x.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf537/boards/cm_bf537e.c
arch/blackfin/mach-bf537/boards/cm_bf537u.c
arch/blackfin/mach-bf537/boards/dnp5370.c
arch/blackfin/mach-bf537/boards/minotaur.c
arch/blackfin/mach-bf537/boards/pnav10.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/boards/tcm_bf537.c
arch/blackfin/mach-bf538/boards/ezkit.c
arch/blackfin/mach-bf548/boards/cm_bf548.c
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf561/boards/acvilon.c
arch/blackfin/mach-bf561/boards/cm_bf561.c
arch/blackfin/mach-bf561/boards/ezkit.c
arch/blackfin/mach-bf561/boards/tepla.c
arch/cris/arch-v10/drivers/Kconfig
arch/cris/arch-v32/drivers/Kconfig
arch/cris/arch-v32/drivers/mach-a3/nandflash.c
arch/cris/arch-v32/drivers/mach-fs/nandflash.c
arch/m68k/Kconfig
arch/m68k/Kconfig.bus
arch/m68k/Kconfig.devices
arch/m68k/amiga/amiints.c
arch/m68k/amiga/cia.c
arch/m68k/apollo/dn_ints.c
arch/m68k/atari/ataints.c
arch/m68k/bvme6000/config.c
arch/m68k/hp300/time.c
arch/m68k/include/asm/hardirq.h
arch/m68k/include/asm/irq.h
arch/m68k/include/asm/macintosh.h
arch/m68k/include/asm/q40ints.h
arch/m68k/kernel/Makefile
arch/m68k/kernel/entry_mm.S
arch/m68k/kernel/ints.c
arch/m68k/mac/baboon.c
arch/m68k/mac/iop.c
arch/m68k/mac/macints.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/q40ints.c
arch/m68k/sun3/sun3ints.c
arch/microblaze/include/asm/namei.h [deleted file]
arch/mips/Makefile
arch/mips/cavium-octeon/flash_setup.c
arch/mips/cavium-octeon/smp.c
arch/mips/emma/common/prom.c
arch/mips/include/asm/mach-bcm47xx/gpio.h
arch/mips/include/asm/unistd.h
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cpufreq/loongson2_clock.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/traps.c
arch/mips/lantiq/clk.c
arch/mips/lantiq/devices.c
arch/mips/lantiq/prom.c
arch/mips/lantiq/setup.c
arch/mips/lantiq/xway/clk-ase.c
arch/mips/lantiq/xway/clk-xway.c
arch/mips/lantiq/xway/devices.c
arch/mips/lantiq/xway/dma.c
arch/mips/lantiq/xway/gpio.c
arch/mips/lantiq/xway/gpio_ebu.c
arch/mips/lantiq/xway/gpio_stp.c
arch/mips/lantiq/xway/prom-ase.c
arch/mips/lantiq/xway/prom-xway.c
arch/mips/lantiq/xway/reset.c
arch/mips/nxp/pnx8550/common/pci.c [deleted file]
arch/mips/nxp/pnx8550/common/setup.c [deleted file]
arch/mips/pci/pci-alchemy.c
arch/mips/pci/pci-lantiq.c
arch/mips/pmc-sierra/yosemite/prom.c
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/boot/dts/charon.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1023rds.dts
arch/powerpc/configs/52xx/tqm5200_defconfig
arch/powerpc/configs/ppc44x_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/include/asm/atomic.h
arch/powerpc/include/asm/bitops.h
arch/powerpc/include/asm/floppy.h
arch/powerpc/include/asm/futex.h
arch/powerpc/include/asm/kvm.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/lv1call.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/sections.h
arch/powerpc/include/asm/synch.h
arch/powerpc/include/asm/xics.h
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/jump_label.c
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/traps.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/lib/feature-fixups.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/52xx/mpc5200_simple.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/p3060_qds.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/cell/beat.c
arch/powerpc/platforms/cell/celleb_scc_pciex.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/pmu.c
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/ps3/device-init.c
arch/powerpc/platforms/ps3/interrupt.c
arch/powerpc/platforms/ps3/platform.h
arch/powerpc/platforms/ps3/repository.c
arch/powerpc/platforms/ps3/smp.c
arch/powerpc/sysdev/ehv_pic.c
arch/powerpc/sysdev/fsl_lbc.c
arch/powerpc/sysdev/fsl_rio.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/ppc4xx_soc.c
arch/powerpc/sysdev/qe_lib/qe.c
arch/powerpc/sysdev/xics/xics-common.c
arch/s390/Kconfig
arch/s390/crypto/crypt_s390.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/timex.h
arch/s390/include/asm/unistd.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/early.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/topology.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/diag.c
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/mm/fault.c
arch/sh/include/asm/page.h
arch/sh/include/asm/unistd_32.h
arch/sh/include/asm/unistd_64.h
arch/sh/kernel/cpu/sh2a/setup-sh7203.c
arch/sh/kernel/cpu/shmobile/cpuidle.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sparc/include/asm/pgtable_32.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/unistd.h
arch/sparc/kernel/entry.h
arch/sparc/kernel/module.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sigutil_64.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/mm/Makefile
arch/sparc/mm/generic_32.c [deleted file]
arch/sparc/mm/generic_64.c [deleted file]
arch/unicore32/Kconfig
arch/unicore32/Kconfig.debug
arch/unicore32/boot/compressed/Makefile
arch/unicore32/include/asm/bitops.h
arch/unicore32/include/asm/processor.h
arch/unicore32/kernel/ksyms.c
arch/unicore32/lib/findbit.S
arch/x86/include/asm/apic.h
arch/x86/include/asm/mach_traps.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/mrst.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/alternative.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/mcheck/mce-inject.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/kvmclock.c
arch/x86/kernel/nmi.c
arch/x86/kernel/setup.c
arch/x86/kernel/x86_init.c
arch/x86/kvm/vmx.c
arch/x86/platform/ce4100/ce4100.c
arch/x86/platform/mrst/mrst.c
arch/x86/platform/mrst/pmu.c
arch/x86/platform/mrst/vrtc.c
arch/x86/um/asm/processor.h
arch/x86/xen/enlighten.c
arch/x86/xen/grant-table.c
block/blk-core.c
block/blk-map.c
block/genhd.c
crypto/ablkcipher.c
crypto/aead.c
crypto/ahash.c
crypto/blkcipher.c
crypto/crypto_user.c
crypto/pcompress.c
crypto/rng.c
crypto/shash.c
drivers/acpi/acpica/hwregs.c
drivers/acpi/apei/erst.c
drivers/acpi/atomicio.c
drivers/acpi/bus.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/scan.c
drivers/acpi/sysfs.c
drivers/ata/ahci.c
drivers/ata/ahci_platform.c
drivers/ata/libata-eh.c
drivers/ata/libata-pmp.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/pata_of_platform.c
drivers/ata/sata_sis.c
drivers/base/core.c
drivers/base/node.c
drivers/base/power/clock_ops.c
drivers/base/power/main.c
drivers/base/power/opp.c
drivers/base/power/qos.c
drivers/block/cciss.c
drivers/block/cciss_scsi.c
drivers/block/loop.c
drivers/block/paride/pg.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/bcm203x.c
drivers/bluetooth/bfusb.c
drivers/bluetooth/btusb.c
drivers/char/agp/intel-gtt.c
drivers/char/random.c
drivers/cpufreq/db8500-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/driver.c
drivers/cpuidle/governors/ladder.c
drivers/cpuidle/governors/menu.c
drivers/cpuidle/sysfs.c
drivers/crypto/mv_cesa.c
drivers/devfreq/Kconfig
drivers/devfreq/devfreq.c
drivers/edac/mpc85xx_edac.c
drivers/firmware/dmi_scan.c
drivers/firmware/efivars.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pca953x.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/exynos/exynos_drm_buf.c
drivers/gpu/drm/exynos/exynos_drm_buf.h
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_crtc.h
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_drm_encoder.h
drivers/gpu/drm/exynos/exynos_drm_fb.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gem.h
drivers/gpu/drm/i915/i915_debugfs.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_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_i2c.c
drivers/gpu/drm/nouveau/nouveau_perf.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv40_pm.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_grctx.c
drivers/gpu/drm/nouveau/nv50_vram.c
drivers/gpu/drm/nouveau/nvc0_graph.c
drivers/gpu/drm/nouveau/nvc0_grctx.c
drivers/gpu/drm/nouveau/nvc0_vram.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c [new file with mode: 0644]
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_blit_kms.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
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_connectors.c
drivers/gpu/drm/radeon/radeon_cs.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_encoders.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/vga/vgaarb.c
drivers/hwmon/Kconfig
drivers/hwmon/ad7314.c
drivers/hwmon/ads7871.c
drivers/hwmon/exynos4_tmu.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/jz4740-hwmon.c
drivers/hwmon/ntc_thermistor.c
drivers/hwmon/s3c-hwmon.c
drivers/hwmon/sch5627.c
drivers/hwmon/sch5636.c
drivers/hwmon/twl4030-madc-hwmon.c
drivers/hwmon/ultra45_env.c
drivers/hwmon/wm831x-hwmon.c
drivers/hwmon/wm8350-hwmon.c
drivers/hwspinlock/u8500_hsem.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/busses/i2c-nuc900.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/cy82c693.c
drivers/ide/icside.c
drivers/ide/ide-cd.c
drivers/ide/ide-floppy.c
drivers/ide/ide-tape.c
drivers/ide/piix.c
drivers/ide/triflex.c
drivers/idle/intel_idle.c
drivers/infiniband/core/addr.c
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/qib/qib_qsfp.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/input/mouse/elantech.c
drivers/input/serio/ams_delta_serio.c
drivers/input/serio/i8042-x86ia64io.h
drivers/iommu/omap-iommu-debug.c
drivers/iommu/omap-iovmm.c
drivers/leds/led-class.c
drivers/macintosh/via-macii.c
drivers/macintosh/via-maciisi.c
drivers/md/dm-bufio.c
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree.c
drivers/md/persistent-data/dm-space-map-checker.c
drivers/md/persistent-data/dm-space-map-disk.c
drivers/md/persistent-data/dm-transaction-manager.c
drivers/md/raid5.c
drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
drivers/media/dvb/dvb-usb/mxl111sf-phy.c
drivers/media/video/s5k6aa.c
drivers/media/video/s5p-mfc/s5p_mfc_dec.c
drivers/media/video/s5p-mfc/s5p_mfc_enc.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/v4l2-ctrls.c
drivers/media/video/v4l2-event.c
drivers/media/video/videobuf2-core.c
drivers/mfd/ab5500-core.c
drivers/mfd/ab5500-debugfs.c
drivers/misc/Kconfig
drivers/misc/ad525x_dpot.h
drivers/misc/carma/carma-fpga-program.c
drivers/misc/carma/carma-fpga.c
drivers/misc/eeprom/Kconfig
drivers/misc/pch_phub.c
drivers/misc/spear13xx_pcie_gadget.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mtd/Kconfig
drivers/mtd/Makefile
drivers/mtd/afs.c
drivers/mtd/ar7part.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/fwh_lock.h
drivers/mtd/chips/jedec_probe.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/Kconfig
drivers/mtd/devices/Makefile
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/doc2001.c
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/docecc.c
drivers/mtd/devices/docg3.c [new file with mode: 0644]
drivers/mtd/devices/docg3.h [new file with mode: 0644]
drivers/mtd/devices/docprobe.c
drivers/mtd/devices/lart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/devices/sst25l.c
drivers/mtd/ftl.c
drivers/mtd/inftlcore.c
drivers/mtd/inftlmount.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/bcm963xx-flash.c
drivers/mtd/maps/bfin-async-flash.c
drivers/mtd/maps/ceiva.c [deleted file]
drivers/mtd/maps/dc21285.c
drivers/mtd/maps/edb7312.c [deleted file]
drivers/mtd/maps/gpio-addr-flash.c
drivers/mtd/maps/h720x-flash.c
drivers/mtd/maps/impa7.c
drivers/mtd/maps/intel_vr_nor.c
drivers/mtd/maps/ixp2000.c
drivers/mtd/maps/ixp4xx.c
drivers/mtd/maps/lantiq-flash.c
drivers/mtd/maps/latch-addr-flash.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/maps/physmap.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/maps/plat-ram.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/maps/rbtx4939-flash.c
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/maps/solutionengine.c
drivers/mtd/maps/wr_sbc82xx_flash.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdblock.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdcore.h
drivers/mtd/mtdoops.c
drivers/mtd/mtdpart.c
drivers/mtd/mtdsuper.c
drivers/mtd/mtdswap.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/autcpu12.c
drivers/mtd/nand/bcm_umi_nand.c
drivers/mtd/nand/cafe_nand.c
drivers/mtd/nand/cmx270_nand.c
drivers/mtd/nand/cs553x_nand.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/edb7312.c [deleted file]
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_upm.c
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/gpmi-nand/Makefile [new file with mode: 0644]
drivers/mtd/nand/gpmi-nand/bch-regs.h [new file with mode: 0644]
drivers/mtd/nand/gpmi-nand/gpmi-lib.c [new file with mode: 0644]
drivers/mtd/nand/gpmi-nand/gpmi-nand.c [new file with mode: 0644]
drivers/mtd/nand/gpmi-nand/gpmi-nand.h [new file with mode: 0644]
drivers/mtd/nand/gpmi-nand/gpmi-regs.h [new file with mode: 0644]
drivers/mtd/nand/h1910.c
drivers/mtd/nand/jz4740_nand.c
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_bbt.c
drivers/mtd/nand/nand_bch.c
drivers/mtd/nand/nand_ecc.c
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/ndfc.c
drivers/mtd/nand/nomadik_nand.c
drivers/mtd/nand/nuc900_nand.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/orion_nand.c
drivers/mtd/nand/pasemi_nand.c
drivers/mtd/nand/plat_nand.c
drivers/mtd/nand/ppchameleonevb.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/r852.c
drivers/mtd/nand/rtc_from4.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sharpsl.c
drivers/mtd/nand/sm_common.c
drivers/mtd/nand/socrates_nand.c
drivers/mtd/nand/tmio_nand.c
drivers/mtd/nand/txx9ndfmc.c
drivers/mtd/nftlcore.c
drivers/mtd/nftlmount.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/generic.c
drivers/mtd/onenand/omap2.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/onenand/onenand_bbt.c
drivers/mtd/onenand/samsung.c
drivers/mtd/redboot.c
drivers/mtd/sm_ftl.c
drivers/mtd/ssfdc.c
drivers/mtd/tests/mtd_oobtest.c
drivers/mtd/tests/mtd_pagetest.c
drivers/mtd/tests/mtd_readtest.c
drivers/mtd/tests/mtd_speedtest.c
drivers/mtd/tests/mtd_stresstest.c
drivers/mtd/tests/mtd_subpagetest.c
drivers/mtd/tests/mtd_torturetest.c
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/kapi.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/vtbl.c
drivers/net/Kconfig
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_procfs.c
drivers/net/bonding/bond_sysfs.c
drivers/net/ethernet/Makefile
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/at91_ether.c
drivers/net/ethernet/cadence/at91_ether.h
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/freescale/Kconfig
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/marvell/sky2.h
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/natsemi/Kconfig
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
drivers/net/ethernet/rdc/r6040.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/hippi/Kconfig
drivers/net/macvlan.c
drivers/net/usb/asix.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/lg-vl600.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/usbnet.c
drivers/net/wireless/ath/ath9k/ar9002_calib.c
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ar9485_initvals.h
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/carl9170/tx.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/b43/xmit.c
drivers/net/wireless/b43/xmit.h
drivers/net/wireless/brcm80211/brcmsmac/dma.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-pci.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/cfg.h
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/libertas/main.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/wl12xx/scan.c
drivers/of/irq.c
drivers/pci/Kconfig
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_hpc.c
drivers/pinctrl/Kconfig
drivers/platform/x86/Kconfig
drivers/platform/x86/dell-laptop.c
drivers/pnp/pnpacpi/rsparser.c
drivers/ps3/ps3-vuart.c
drivers/ps3/ps3stor_lib.c
drivers/regulator/aat2870-regulator.c
drivers/regulator/core.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/twl-regulator.c
drivers/rtc/rtc-mrst.c
drivers/rtc/rtc-puv3.c
drivers/s390/char/zcore.c
drivers/s390/crypto/ap_bus.c
drivers/s390/net/Kconfig
drivers/s390/net/lcs.c
drivers/s390/net/netiucv.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/qeth_l3_sys.c
drivers/scsi/aacraid/linit.c
drivers/scsi/hpsa.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/sh/Makefile
drivers/sh/clk/core.c
drivers/sh/pm_runtime.c [new file with mode: 0644]
drivers/spi/spi-atmel.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-pl022.c
drivers/staging/et131x/Kconfig
drivers/staging/et131x/et131x.c
drivers/staging/iio/industrialio-core.c
drivers/staging/media/as102/as102_drv.c
drivers/staging/media/as102/as102_drv.h
drivers/staging/octeon/ethernet-tx.c
drivers/staging/slicoss/Kconfig
drivers/staging/spectra/lld_mtd.c
drivers/thermal/thermal_sys.c
drivers/tty/hvc/hvc_dcc.c
drivers/tty/n_gsm.c
drivers/tty/serial/Kconfig
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/crisv10.c
drivers/tty/serial/mfd.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/sh-sci.c
drivers/tty/tty_ldisc.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/ci13xxx_msm.c
drivers/usb/gadget/ci13xxx_udc.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/f_midi.c
drivers/usb/gadget/f_phonet.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/pch_udc.c
drivers/usb/gadget/r8a66597-udc.c
drivers/usb/gadget/udc-core.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-xls.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci.h
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/musb/Kconfig
drivers/usb/musb/am35x.c
drivers/usb/musb/da8xx.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_gadget.c
drivers/usb/renesas_usbhs/common.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod.h
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/storage/ene_ub6250.c
drivers/usb/storage/protocol.c
drivers/video/da8xx-fb.c
drivers/video/omap/dispc.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/hdmi.c
drivers/video/via/share.h
drivers/virtio/Kconfig
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/adx_wdt.c [deleted file]
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/wm831x_wdt.c
drivers/xen/balloon.c
drivers/xen/gntalloc.c
drivers/xen/gntdev.c
drivers/xen/xenbus/xenbus_client.c
fs/bio.c
fs/btrfs/backref.c
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/free-space-cache.c
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/ceph/dir.c
fs/ceph/inode.c
fs/ceph/super.c
fs/cifs/file.c
fs/dcache.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ext4/balloc.c
fs/ext4/inode.c
fs/ext4/super.c
fs/hfs/trans.c
fs/jffs2/compr.c
fs/jffs2/compr.h
fs/jffs2/fs.c
fs/jffs2/jffs2_fs_sb.h
fs/jffs2/os-linux.h
fs/jffs2/scan.c
fs/jffs2/super.c
fs/jffs2/wbuf.c
fs/minix/bitmap.c
fs/minix/inode.c
fs/minix/minix.h
fs/namei.c
fs/namespace.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/aops.h
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/netdebug.c
fs/ocfs2/cluster/tcp.c
fs/ocfs2/cluster/tcp.h
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmcommon.h
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmlock.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/dlmthread.c
fs/ocfs2/dlmglue.c
fs/ocfs2/extent_map.c
fs/ocfs2/extent_map.h
fs/ocfs2/file.c
fs/ocfs2/inode.c
fs/ocfs2/inode.h
fs/ocfs2/ioctl.c
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/mmap.c
fs/ocfs2/move_extents.c
fs/ocfs2/ocfs2.h
fs/ocfs2/quota_local.c
fs/ocfs2/slot_map.c
fs/ocfs2/stack_o2cb.c
fs/ocfs2/super.c
fs/ocfs2/xattr.c
fs/proc/base.c
fs/pstore/platform.c
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/recovery.c
fs/ubifs/sb.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_dquot_item.c
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log.h
fs/xfs/xfs_qm.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_vnodeops.c
include/acpi/acpi_drivers.h
include/acpi/actypes.h
include/acpi/processor.h
include/drm/drmP.h
include/drm/drm_dp_helper.h
include/drm/drm_mode.h
include/drm/drm_pciids.h
include/drm/exynos_drm.h
include/drm/radeon_drm.h
include/drm/vmwgfx_drm.h
include/linux/bio.h
include/linux/ceph/osd_client.h
include/linux/clocksource.h
include/linux/cpuidle.h
include/linux/devfreq.h
include/linux/device.h
include/linux/ethtool.h
include/linux/fs.h
include/linux/genhd.h
include/linux/hugetlb.h
include/linux/hwspinlock.h
include/linux/i2c.h
include/linux/inet_diag.h
include/linux/init_task.h
include/linux/kvm.h
include/linux/mfd/tps65910.h
include/linux/mfd/wm8994/registers.h
include/linux/mtd/bbm.h
include/linux/mtd/mtd.h
include/linux/mtd/nand.h
include/linux/mtd/onenand.h
include/linux/mtd/partitions.h
include/linux/mtd/physmap.h
include/linux/nfs_fs.h
include/linux/nfs_xdr.h
include/linux/pci-ats.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/pinctrl/pinctrl.h
include/linux/platform_data/macb.h [new file with mode: 0644]
include/linux/pm.h
include/linux/pm_runtime.h
include/linux/pstore.h
include/linux/sched.h
include/linux/serial.h
include/linux/serial_sci.h
include/linux/sh_clk.h
include/linux/sh_pfc.h
include/linux/virtio_config.h
include/linux/virtio_mmio.h
include/linux/vmalloc.h
include/mtd/mtd-abi.h
include/net/bluetooth/l2cap.h
include/net/bluetooth/rfcomm.h
include/net/cfg80211.h
include/net/mac80211.h
include/net/netlink.h
include/sound/saif.h
include/video/omapdss.h
include/xen/platform_pci.h
kernel/cgroup_freezer.c
kernel/fork.c
kernel/hrtimer.c
kernel/irq/manage.c
kernel/irq/spurious.c
kernel/power/hibernate.c
kernel/power/main.c
kernel/power/qos.c
kernel/time/clocksource.c
kernel/time/timekeeping.c
lib/nlattr.c
mm/backing-dev.c
mm/hugetlb.c
mm/nommu.c
mm/oom_kill.c
mm/page-writeback.c
mm/percpu-vm.c
mm/percpu.c
mm/slub.c
mm/vmalloc.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/l2cap_core.c
net/bluetooth/mgmt.c
net/bluetooth/rfcomm/core.c
net/bridge/br_multicast.c
net/ceph/osd_client.c
net/ipv4/ah4.c
net/ipv4/inet_diag.c
net/ipv4/ip_options.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/ah6.c
net/ipv6/ip6_input.c
net/ipv6/ip6_tunnel.c
net/l2tp/l2tp_core.c
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/util.c
net/mac80211/work.c
net/rds/Kconfig
net/sunrpc/xprtsock.c
net/wanrouter/wanproc.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/scan.c
security/keys/encrypted-keys/Makefile
security/keys/encrypted-keys/encrypted.c
security/keys/encrypted-keys/encrypted.h
security/keys/user_defined.c
security/smack/smackfs.c
sound/core/vmaster.c
sound/pci/cs5535audio/cs5535audio_pcm.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/intel8x0.c
sound/pci/lx6464es/lx_core.c
sound/pci/lx6464es/lx_core.h
sound/pci/rme9652/hdspm.c
sound/ppc/snd_ps3.c
sound/soc/codecs/adau1373.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/rt5631.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sta32x.c
sound/soc/codecs/sta32x.h
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9090.c
sound/soc/codecs/wm_hubs.c
sound/soc/fsl/fsl_ssi.c
sound/soc/mxs/mxs-saif.c
sound/soc/nuc900/nuc900-ac97.c
sound/usb/mixer.c
sound/usb/quirks.c
tools/perf/builtin-record.c
tools/perf/builtin-stat.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/util/annotate.c
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/python.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/top.h
tools/perf/util/trace-event-info.c
tools/perf/util/ui/browser.c
tools/perf/util/ui/browser.h
tools/perf/util/ui/browsers/annotate.c
tools/perf/util/ui/browsers/hists.c
tools/perf/util/ui/helpline.c
tools/perf/util/ui/helpline.h
tools/perf/util/ui/progress.c
tools/perf/util/ui/progress.h
tools/perf/util/ui/setup.c
tools/perf/util/ui/ui.h
tools/perf/util/ui/util.c
tools/perf/util/ui/util.h
tools/power/x86/turbostat/turbostat.c
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf

index a4806f0de852079a2b2d093c30ba05d478df7ec5..9b0d0267a3c3f1ea75a674fe858fac2165a8b683 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -68,6 +68,7 @@ Juha Yrjola <juha.yrjola@solidboot.com>
 Kay Sievers <kay.sievers@vrfy.org>
 Kenneth W Chen <kenneth.w.chen@intel.com>
 Koushik <raghavendra.koushik@neterion.com>
+Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 Leonid I Ananiev <leonid.i.ananiev@intel.com>
 Linas Vepstas <linas@austin.ibm.com>
 Mark Brown <broonie@sirena.org.uk>
@@ -111,3 +112,4 @@ Uwe Kleine-König <ukl@pengutronix.de>
 Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
 Takashi YOSHII <takashi.yoshii.zj@renesas.com>
+Yusuke Goda <goda.yusuke@renesas.com>
diff --git a/Documentation/ABI/stable/sysfs-acpi-pmprofile b/Documentation/ABI/stable/sysfs-acpi-pmprofile
new file mode 100644 (file)
index 0000000..964c7a8
--- /dev/null
@@ -0,0 +1,22 @@
+What:          /sys/firmware/acpi/pm_profile
+Date:          03-Nov-2011
+KernelVersion: v3.2
+Contact:       linux-acpi@vger.kernel.org
+Description:   The ACPI pm_profile sysfs interface exports the platform
+               power management (and performance) requirement expectations
+               as provided by BIOS. The integer value is directly passed as
+               retrieved from the FADT ACPI table.
+Values:         For possible values see ACPI specification:
+               5.2.9 Fixed ACPI Description Table (FADT)
+               Field: Preferred_PM_Profile
+
+               Currently these values are defined by spec:
+               0 Unspecified
+               1 Desktop
+               2 Mobile
+               3 Workstation
+               4 Enterprise Server
+               5 SOHO Server
+               6 Appliance PC
+               7 Performance Server
+               >7 Reserved
index 2b5d56127fce4d7f9a6f83b535cdfcf469f83e0b..c1eb41cb9876083d3df79a6a995b692762acd21b 100644 (file)
@@ -206,16 +206,3 @@ Description:
                when a discarded area is read the discard_zeroes_data
                parameter will be set to one. Otherwise it will be 0 and
                the result of reading a discarded area is undefined.
-What:          /sys/block/<disk>/alias
-Date:          Aug 2011
-Contact:       Nao Nishijima <nao.nishijima.xt@hitachi.com>
-Description:
-               A raw device name of a disk does not always point a same disk
-               each boot-up time. Therefore, users have to use persistent
-               device names, which udev creates when the kernel finds a disk,
-               instead of raw device name. However, kernel doesn't show those
-               persistent names on its messages (e.g. dmesg).
-               This file can store an alias of the disk and it would be
-               appeared in kernel messages if it is set. A disk can have an
-               alias which length is up to 255bytes. Users can use alphabets,
-               numbers, "-" and "_" in alias name. This file is writeonce.
index c2791589397479594eb1d06e61567f404f3057c4..196b8b9dba1112b245e331a76b62e804604b191a 100644 (file)
@@ -32,7 +32,7 @@
       The Linux DRM layer contains code intended to support the needs
       of complex graphics devices, usually containing programmable
       pipelines well suited to 3D graphics acceleration.  Graphics
-      drivers in the kernel can make use of DRM functions to make
+      drivers in the kernel may make use of DRM functions to make
       tasks like memory management, interrupt handling and DMA easier,
       and provide a uniform interface to applications.
     </para>
       existing drivers.
     </para>
     <para>
-      First, we'll go over some typical driver initialization
+      First, we go over some typical driver initialization
       requirements, like setting up command buffers, creating an
       initial output configuration, and initializing core services.
-      Subsequent sections will cover core internals in more detail,
+      Subsequent sections cover core internals in more detail,
       providing implementation notes and examples.
     </para>
     <para>
@@ -74,7 +74,7 @@
     </para>
     <para>
       The core of every DRM driver is struct drm_driver.  Drivers
-      will typically statically initialize a drm_driver structure,
+      typically statically initialize a drm_driver structure,
       then pass it to drm_init() at load time.
     </para>
 
@@ -88,8 +88,8 @@
     </para>
     <programlisting>
       static struct drm_driver driver = {
-       /* don't use mtrr's here, the Xserver or user space app should
-        * deal with them for intel hardware.
+       /* Don't use MTRRs here; the Xserver or userspace app should
+        * deal with them for Intel hardware.
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
     </programlisting>
     <para>
       In the example above, taken from the i915 DRM driver, the driver
-      sets several flags indicating what core features it supports.
-      We'll go over the individual callbacks in later sections.  Since
+      sets several flags indicating what core features it supports;
+      we go over the individual callbacks in later sections.  Since
       flags indicate which features your driver supports to the DRM
       core, you need to set most of them prior to calling drm_init().  Some,
       like DRIVER_MODESET can be set later based on user supplied parameters,
        <term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
        <listitem>
          <para>
-           DRIVER_HAVE_IRQ indicates whether the driver has a IRQ
-           handler, DRIVER_IRQ_SHARED indicates whether the device &amp;
+           DRIVER_HAVE_IRQ indicates whether the driver has an IRQ
+           handler DRIVER_IRQ_SHARED indicates whether the device &amp;
            handler support shared IRQs (note that this is required of
            PCI drivers).
          </para>
        <term>DRIVER_DMA_QUEUE</term>
        <listitem>
          <para>
-           If the driver queues DMA requests and completes them
-           asynchronously, this flag should be set.  Deprecated.
+           Should be set if the driver queues DMA requests and completes them
+           asynchronously.  Deprecated.
          </para>
        </listitem>
       </varlistentry>
     </variablelist>
     <para>
       In this specific case, the driver requires AGP and supports
-      IRQs.  DMA, as we'll see, is handled by device specific ioctls
+      IRQs.  DMA, as discussed later, is handled by device-specific ioctls
       in this case.  It also supports the kernel mode setting APIs, though
       unlike in the actual i915 driver source, this example unconditionally
       exports KMS capability.
       initial output configuration.
     </para>
     <para>
-      Note that the tasks performed at driver load time must not
-      conflict with DRM client requirements.  For instance, if user
+      If compatibility is a concern (e.g. with drivers converted over
+      to the new interfaces from the old ones), care must be taken to
+      prevent device initialization and control that is incompatible with
+      currently active userspace drivers.  For instance, if user
       level mode setting drivers are in use, it would be problematic
       to perform output discovery &amp; configuration at load time.
-      Likewise, if pre-memory management aware user level drivers are
+      Likewise, if user-level drivers unaware of memory management are
       in use, memory management and command buffer setup may need to
-      be omitted.  These requirements are driver specific, and care
+      be omitted.  These requirements are driver-specific, and care
       needs to be taken to keep both old and new applications and
       libraries working.  The i915 driver supports the "modeset"
       module parameter to control whether advanced features are
-      enabled at load time or in legacy fashion.  If compatibility is
-      a concern (e.g. with drivers converted over to the new interfaces
-      from the old ones), care must be taken to prevent incompatible
-      device initialization and control with the currently active
-      userspace drivers.
+      enabled at load time or in legacy fashion.
     </para>
 
     <sect2>
       <title>Driver private &amp; performance counters</title>
       <para>
        The driver private hangs off the main drm_device structure and
-       can be used for tracking various device specific bits of
+       can be used for tracking various device-specific bits of
        information, like register offsets, command buffer status,
        register state for suspend/resume, etc.  At load time, a
-       driver can simply allocate one and set drm_device.dev_priv
-       appropriately; at unload the driver can free it and set
-       drm_device.dev_priv to NULL.
+       driver may simply allocate one and set drm_device.dev_priv
+       appropriately; it should be freed and drm_device.dev_priv set
+       to NULL when the driver is unloaded.
       </para>
       <para>
-       The DRM supports several counters which can be used for rough
+       The DRM supports several counters which may be used for rough
        performance characterization.  Note that the DRM stat counter
        system is not often used by applications, and supporting
        additional counters is completely optional.
        These interfaces are deprecated and should not be used.  If performance
        monitoring is desired, the developer should investigate and
        potentially enhance the kernel perf and tracing infrastructure to export
-       GPU related performance information to performance monitoring
-       tools and applications.
+       GPU related performance information for consumption by performance
+       monitoring tools and applications.
       </para>
     </sect2>
 
     <sect2>
       <title>Configuring the device</title>
       <para>
-       Obviously, device configuration will be device specific.
+       Obviously, device configuration is device-specific.
        However, there are several common operations: finding a
        device's PCI resources, mapping them, and potentially setting
        up an IRQ handler.
       <para>
        Finding &amp; mapping resources is fairly straightforward.  The
        DRM wrapper functions, drm_get_resource_start() and
-       drm_get_resource_len() can be used to find BARs on the given
+       drm_get_resource_len(), may be used to find BARs on the given
        drm_device struct.  Once those values have been retrieved, the
        driver load function can call drm_addmap() to create a new
-       mapping for the BAR in question.  Note you'll probably want a
+       mapping for the BAR in question.  Note that you probably want a
        drm_local_map_t in your driver private structure to track any
        mappings you create.
 <!-- !Fdrivers/gpu/drm/drm_bufs.c drm_get_resource_* -->
       <para>
        if compatibility with other operating systems isn't a concern
        (DRM drivers can run under various BSD variants and OpenSolaris),
-       native Linux calls can be used for the above, e.g. pci_resource_*
+       native Linux calls may be used for the above, e.g. pci_resource_*
        and iomap*/iounmap.  See the Linux device driver book for more
        info.
       </para>
       <para>
-       Once you have a register map, you can use the DRM_READn() and
+       Once you have a register map, you may use the DRM_READn() and
        DRM_WRITEn() macros to access the registers on your device, or
-       use driver specific versions to offset into your MMIO space
-       relative to a driver specific base pointer (see I915_READ for
-       example).
+       use driver-specific versions to offset into your MMIO space
+       relative to a driver-specific base pointer (see I915_READ for
+       an example).
       </para>
       <para>
        If your device supports interrupt generation, you may want to
-       setup an interrupt handler at driver load time as well.  This
+       set up an interrupt handler when the driver is loaded.  This
        is done using the drm_irq_install() function.  If your device
        supports vertical blank interrupts, it should call
        drm_vblank_init() to initialize the core vblank handling code before
       </para>
 <!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
       <para>
-       Once your interrupt handler is registered (it'll use your
+       Once your interrupt handler is registered (it uses your
        drm_driver.irq_handler as the actual interrupt handling
        function), you can safely enable interrupts on your device,
        assuming any other state your interrupt handler uses is also
        using the pci_map_rom() call, a convenience function that
        takes care of mapping the actual ROM, whether it has been
        shadowed into memory (typically at address 0xc0000) or exists
-       on the PCI device in the ROM BAR.  Note that once you've
-       mapped the ROM and extracted any necessary information, be
-       sure to unmap it; on many devices the ROM address decoder is
-       shared with other BARs, so leaving it mapped can cause
+       on the PCI device in the ROM BAR.  Note that after the ROM
+       has been mapped and any necessary information has been extracted,
+       it should be unmapped; on many devices, the ROM address decoder is
+       shared with other BARs, so leaving it mapped could cause
        undesired behavior like hangs or memory corruption.
 <!--!Fdrivers/pci/rom.c pci_map_rom-->
       </para>
        should support a memory manager.
       </para>
       <para>
-       If your driver supports memory management (it should!), you'll
+       If your driver supports memory management (it should!), you
        need to set that up at load time as well.  How you initialize
-       it depends on which memory manager you're using, TTM or GEM.
+       it depends on which memory manager you're using: TTM or GEM.
       </para>
       <sect3>
        <title>TTM initialization</title>
          and devices with dedicated video RAM (VRAM), i.e. most discrete
          graphics devices.  If your device has dedicated RAM, supporting
          TTM is desirable.  TTM also integrates tightly with your
-         driver specific buffer execution function.  See the radeon
+         driver-specific buffer execution function.  See the radeon
          driver for examples.
        </para>
        <para>
          created by the memory manager at runtime.  Your global TTM should
          have a type of TTM_GLOBAL_TTM_MEM.  The size field for the global
          object should be sizeof(struct ttm_mem_global), and the init and
-         release hooks should point at your driver specific init and
-         release routines, which will probably eventually call
-         ttm_mem_global_init and ttm_mem_global_release respectively.
+         release hooks should point at your driver-specific init and
+         release routines, which probably eventually call
+         ttm_mem_global_init and ttm_mem_global_release, respectively.
        </para>
        <para>
          Once your global TTM accounting structure is set up and initialized
-         (done by calling ttm_global_item_ref on the global object you
-         just created), you'll need to create a buffer object TTM to
+         by calling ttm_global_item_ref() on it,
+         you need to create a buffer object TTM to
          provide a pool for buffer object allocation by clients and the
          kernel itself.  The type of this object should be TTM_GLOBAL_TTM_BO,
          and its size should be sizeof(struct ttm_bo_global).  Again,
-         driver specific init and release functions can be provided,
-         likely eventually calling ttm_bo_global_init and
-         ttm_bo_global_release, respectively.  Also like the previous
-         object, ttm_global_item_ref is used to create an initial reference
+         driver-specific init and release functions may be provided,
+         likely eventually calling ttm_bo_global_init() and
+         ttm_bo_global_release(), respectively.  Also, like the previous
+         object, ttm_global_item_ref() is used to create an initial reference
          count for the TTM, which will call your initialization function.
        </para>
       </sect3>
          GEM is an alternative to TTM, designed specifically for UMA
          devices.  It has simpler initialization and execution requirements
          than TTM, but has no VRAM management capability.  Core GEM
-         initialization is comprised of a basic drm_mm_init call to create
+         is initialized by calling drm_mm_init() to create
          a GTT DRM MM object, which provides an address space pool for
-         object allocation.  In a KMS configuration, the driver will
-         need to allocate and initialize a command ring buffer following
-         basic GEM initialization.  Most UMA devices have a so-called
+         object allocation.  In a KMS configuration, the driver
+         needs to allocate and initialize a command ring buffer following
+         core GEM initialization.  A UMA device usually has what is called a
          "stolen" memory region, which provides space for the initial
          framebuffer and large, contiguous memory regions required by the
-         device.  This space is not typically managed by GEM, and must
+         device.  This space is not typically managed by GEM, and it must
          be initialized separately into its own DRM MM object.
        </para>
        <para>
-         Initialization will be driver specific, and will depend on
-         the architecture of the device.  In the case of Intel
+         Initialization is driver-specific. In the case of Intel
          integrated graphics chips like 965GM, GEM initialization can
          be done by calling the internal GEM init function,
          i915_gem_do_init().  Since the 965GM is a UMA device
-         (i.e. it doesn't have dedicated VRAM), GEM will manage
+         (i.e. it doesn't have dedicated VRAM), GEM manages
          making regular RAM available for GPU operations.  Memory set
          aside by the BIOS (called "stolen" memory by the i915
-         driver) will be managed by the DRM memrange allocator; the
-         rest of the aperture will be managed by GEM.
+         driver) is managed by the DRM memrange allocator; the
+         rest of the aperture is managed by GEM.
          <programlisting>
            /* Basic memrange allocator for stolen space (aka vram) */
            drm_memrange_init(&amp;dev_priv->vram, 0, prealloc_size);
 <!--!Edrivers/char/drm/drm_memrange.c-->
        </para>
        <para>
-         Once the memory manager has been set up, we can allocate the
+         Once the memory manager has been set up, we may allocate the
          command buffer.  In the i915 case, this is also done with a
          GEM function, i915_gem_init_ringbuffer().
        </para>
     <sect2>
       <title>Output configuration</title>
       <para>
-       The final initialization task is output configuration.  This involves
-       finding and initializing the CRTCs, encoders and connectors
-       for your device, creating an initial configuration and
-       registering a framebuffer console driver.
+       The final initialization task is output configuration.  This involves:
+       <itemizedlist>
+         <listitem>
+           Finding and initializing the CRTCs, encoders, and connectors
+           for the device.
+         </listitem>
+         <listitem>
+           Creating an initial configuration.
+         </listitem>
+         <listitem>
+           Registering a framebuffer console driver.
+         </listitem>
+       </itemizedlist>
       </para>
       <sect3>
        <title>Output discovery and initialization</title>
        <para>
-         Several core functions exist to create CRTCs, encoders and
-         connectors, namely drm_crtc_init(), drm_connector_init() and
+         Several core functions exist to create CRTCs, encoders, and
+         connectors, namely: drm_crtc_init(), drm_connector_init(), and
          drm_encoder_init(), along with several "helper" functions to
          perform common tasks.
        </para>
@@ -555,10 +561,10 @@ void intel_crt_init(struct drm_device *dev)
        </programlisting>
        <para>
          In the example above (again, taken from the i915 driver), a
-         CRT connector and encoder combination is created.  A device
-         specific i2c bus is also created, for fetching EDID data and
+         CRT connector and encoder combination is created.  A device-specific
+         i2c bus is also created for fetching EDID data and
          performing monitor detection.  Once the process is complete,
-         the new connector is registered with sysfs, to make its
+         the new connector is registered with sysfs to make its
          properties available to applications.
        </para>
        <sect4>
@@ -567,12 +573,12 @@ void intel_crt_init(struct drm_device *dev)
            Since many PC-class graphics devices have similar display output
            designs, the DRM provides a set of helper functions to make
            output management easier.  The core helper routines handle
-           encoder re-routing and disabling of unused functions following
-           mode set.  Using the helpers is optional, but recommended for
+           encoder re-routing and the disabling of unused functions following
+           mode setting.  Using the helpers is optional, but recommended for
            devices with PC-style architectures (i.e. a set of display planes
            for feeding pixels to encoders which are in turn routed to
            connectors).  Devices with more complex requirements needing
-           finer grained management can opt to use the core callbacks
+           finer grained management may opt to use the core callbacks
            directly.
          </para>
          <para>
@@ -580,17 +586,25 @@ void intel_crt_init(struct drm_device *dev)
          </para>
        </sect4>
        <para>
-         For each encoder, CRTC and connector, several functions must
-         be provided, depending on the object type.  Encoder objects
-         need to provide a DPMS (basically on/off) function, mode fixup
-         (for converting requested modes into native hardware timings),
-         and prepare, set and commit functions for use by the core DRM
-         helper functions.  Connector helpers need to provide mode fetch and
-         validity functions as well as an encoder matching function for
-         returning an ideal encoder for a given connector.  The core
-         connector functions include a DPMS callback, (deprecated)
-         save/restore routines, detection, mode probing, property handling,
-         and cleanup functions.
+         Each encoder object needs to provide:
+         <itemizedlist>
+           <listitem>
+             A DPMS (basically on/off) function.
+           </listitem>
+           <listitem>
+             A mode-fixup function (for converting requested modes into
+             native hardware timings).
+           </listitem>
+           <listitem>
+             Functions (prepare, set, and commit) for use by the core DRM
+             helper functions.
+           </listitem>
+         </itemizedlist>
+         Connector helpers need to provide functions (mode-fetch, validity,
+         and encoder-matching) for returning an ideal encoder for a given
+         connector.  The core connector functions include a DPMS callback,
+         save/restore routines (deprecated), detection, mode probing,
+         property handling, and cleanup functions.
        </para>
 <!--!Edrivers/char/drm/drm_crtc.h-->
 <!--!Edrivers/char/drm/drm_crtc.c-->
@@ -605,22 +619,33 @@ void intel_crt_init(struct drm_device *dev)
     <title>VBlank event handling</title>
     <para>
       The DRM core exposes two vertical blank related ioctls:
-      DRM_IOCTL_WAIT_VBLANK and DRM_IOCTL_MODESET_CTL.
+      <variablelist>
+        <varlistentry>
+          <term>DRM_IOCTL_WAIT_VBLANK</term>
+          <listitem>
+            <para>
+              This takes a struct drm_wait_vblank structure as its argument,
+              and it is used to block or request a signal when a specified
+              vblank event occurs.
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>DRM_IOCTL_MODESET_CTL</term>
+          <listitem>
+            <para>
+              This should be called by application level drivers before and
+              after mode setting, since on many devices the vertical blank
+              counter is reset at that time.  Internally, the DRM snapshots
+              the last vblank count when the ioctl is called with the
+              _DRM_PRE_MODESET command, so that the counter won't go backwards
+              (which is dealt with when _DRM_POST_MODESET is used).
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
 <!--!Edrivers/char/drm/drm_irq.c-->
     </para>
-    <para>
-      DRM_IOCTL_WAIT_VBLANK takes a struct drm_wait_vblank structure
-      as its argument, and is used to block or request a signal when a
-      specified vblank event occurs.
-    </para>
-    <para>
-      DRM_IOCTL_MODESET_CTL should be called by application level
-      drivers before and after mode setting, since on many devices the
-      vertical blank counter will be reset at that time.  Internally,
-      the DRM snapshots the last vblank count when the ioctl is called
-      with the _DRM_PRE_MODESET command so that the counter won't go
-      backwards (which is dealt with when _DRM_POST_MODESET is used).
-    </para>
     <para>
       To support the functions above, the DRM core provides several
       helper functions for tracking vertical blank counters, and
@@ -632,24 +657,24 @@ void intel_crt_init(struct drm_device *dev)
       register.  The enable and disable vblank callbacks should enable
       and disable vertical blank interrupts, respectively.  In the
       absence of DRM clients waiting on vblank events, the core DRM
-      code will use the disable_vblank() function to disable
-      interrupts, which saves power.  They'll be re-enabled again when
+      code uses the disable_vblank() function to disable
+      interrupts, which saves power.  They are re-enabled again when
       a client calls the vblank wait ioctl above.
     </para>
     <para>
-      Devices that don't provide a count register can simply use an
+      A device that doesn't provide a count register may simply use an
       internal atomic counter incremented on every vertical blank
-      interrupt, and can make their enable and disable vblank
-      functions into no-ops.
+      interrupt (and then treat the enable_vblank() and disable_vblank()
+      callbacks as no-ops).
     </para>
   </sect1>
 
   <sect1>
     <title>Memory management</title>
     <para>
-      The memory manager lies at the heart of many DRM operations, and
-      is also required to support advanced client features like OpenGL
-      pbuffers.  The DRM currently contains two memory managers, TTM
+      The memory manager lies at the heart of many DRM operations; it
+      is required to support advanced client features like OpenGL
+      pbuffers.  The DRM currently contains two memory managers: TTM
       and GEM.
     </para>
 
@@ -679,41 +704,46 @@ void intel_crt_init(struct drm_device *dev)
       <para>
        GEM-enabled drivers must provide gem_init_object() and
        gem_free_object() callbacks to support the core memory
-       allocation routines.  They should also provide several driver
-       specific ioctls to support command execution, pinning, buffer
+       allocation routines.  They should also provide several driver-specific
+       ioctls to support command execution, pinning, buffer
        read &amp; write, mapping, and domain ownership transfers.
       </para>
       <para>
-       On a fundamental level, GEM involves several operations: memory
-       allocation and freeing, command execution, and aperture management
-       at command execution time.  Buffer object allocation is relatively
+       On a fundamental level, GEM involves several operations:
+       <itemizedlist>
+         <listitem>Memory allocation and freeing</listitem>
+         <listitem>Command execution</listitem>
+         <listitem>Aperture management at command execution time</listitem>
+       </itemizedlist>
+       Buffer object allocation is relatively
        straightforward and largely provided by Linux's shmem layer, which
        provides memory to back each object.  When mapped into the GTT
        or used in a command buffer, the backing pages for an object are
        flushed to memory and marked write combined so as to be coherent
-       with the GPU.  Likewise, when the GPU finishes rendering to an object,
-       if the CPU accesses it, it must be made coherent with the CPU's view
+       with the GPU.  Likewise, if the CPU accesses an object after the GPU
+       has finished rendering to the object, then the object must be made
+       coherent with the CPU's view
        of memory, usually involving GPU cache flushing of various kinds.
-       This core CPU&lt;-&gt;GPU coherency management is provided by the GEM
-       set domain function, which evaluates an object's current domain and
+       This core CPU&lt;-&gt;GPU coherency management is provided by a
+       device-specific ioctl, which evaluates an object's current domain and
        performs any necessary flushing or synchronization to put the object
        into the desired coherency domain (note that the object may be busy,
-       i.e. an active render target; in that case the set domain function
-       will block the client and wait for rendering to complete before
+       i.e. an active render target; in that case, setting the domain
+       blocks the client and waits for rendering to complete before
        performing any necessary flushing operations).
       </para>
       <para>
        Perhaps the most important GEM function is providing a command
        execution interface to clients.  Client programs construct command
-       buffers containing references to previously allocated memory objects
-       and submit them to GEM.  At that point, GEM will take care to bind
+       buffers containing references to previously allocated memory objects,
+       and then submit them to GEM.  At that point, GEM takes care to bind
        all the objects into the GTT, execute the buffer, and provide
        necessary synchronization between clients accessing the same buffers.
        This often involves evicting some objects from the GTT and re-binding
        others (a fairly expensive operation), and providing relocation
        support which hides fixed GTT offsets from clients.  Clients must
        take care not to submit command buffers that reference more objects
-       than can fit in the GTT or GEM will reject them and no rendering
+       than can fit in the GTT; otherwise, GEM will reject them and no rendering
        will occur.  Similarly, if several objects in the buffer require
        fence registers to be allocated for correct rendering (e.g. 2D blits
        on pre-965 chips), care must be taken not to require more fence
@@ -729,7 +759,7 @@ void intel_crt_init(struct drm_device *dev)
     <title>Output management</title>
     <para>
       At the core of the DRM output management code is a set of
-      structures representing CRTCs, encoders and connectors.
+      structures representing CRTCs, encoders, and connectors.
     </para>
     <para>
       A CRTC is an abstraction representing a part of the chip that
@@ -765,21 +795,19 @@ void intel_crt_init(struct drm_device *dev)
   <sect1>
     <title>Framebuffer management</title>
     <para>
-      In order to set a mode on a given CRTC, encoder and connector
-      configuration, clients need to provide a framebuffer object which
-      will provide a source of pixels for the CRTC to deliver to the encoder(s)
-      and ultimately the connector(s) in the configuration.  A framebuffer
-      is fundamentally a driver specific memory object, made into an opaque
-      handle by the DRM addfb function.  Once an fb has been created this
-      way it can be passed to the KMS mode setting routines for use in
-      a configuration.
+      Clients need to provide a framebuffer object which provides a source
+      of pixels for a CRTC to deliver to the encoder(s) and ultimately the
+      connector(s). A framebuffer is fundamentally a driver-specific memory
+      object, made into an opaque handle by the DRM's addfb() function.
+      Once a framebuffer has been created this way, it may be passed to the
+      KMS mode setting routines for use in a completed configuration.
     </para>
   </sect1>
 
   <sect1>
     <title>Command submission &amp; fencing</title>
     <para>
-      This should cover a few device specific command submission
+      This should cover a few device-specific command submission
       implementations.
     </para>
   </sect1>
@@ -789,7 +817,7 @@ void intel_crt_init(struct drm_device *dev)
     <para>
       The DRM core provides some suspend/resume code, but drivers
       wanting full suspend/resume support should provide save() and
-      restore() functions.  These will be called at suspend,
+      restore() functions.  These are called at suspend,
       hibernate, or resume time, and should perform any state save or
       restore required by your device across suspend or hibernate
       states.
@@ -812,8 +840,8 @@ void intel_crt_init(struct drm_device *dev)
     <para>
       The DRM core exports several interfaces to applications,
       generally intended to be used through corresponding libdrm
-      wrapper functions.  In addition, drivers export device specific
-      interfaces for use by userspace drivers &amp; device aware
+      wrapper functions.  In addition, drivers export device-specific
+      interfaces for use by userspace drivers &amp; device-aware
       applications through ioctls and sysfs files.
     </para>
     <para>
@@ -822,8 +850,8 @@ void intel_crt_init(struct drm_device *dev)
       management, memory management, and output management.
     </para>
     <para>
-      Cover generic ioctls and sysfs layout here.  Only need high
-      level info, since man pages will cover the rest.
+      Cover generic ioctls and sysfs layout here.  We only need high-level
+      info, since man pages should cover the rest.
     </para>
   </chapter>
 
index 17910e2052addefcc2a581fa810991fde2545820..0c674be0d3c6de3d05e1903f6fac4beecff51133 100644 (file)
@@ -572,7 +572,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
                        </para>
                        <para>
                                The simplest way to activate the FLASH based bad block table support 
-                               is to set the option NAND_USE_FLASH_BBT in the option field of
+                               is to set the option NAND_BBT_USE_FLASH in the bbt_option field of
                                the nand chip structure before calling nand_scan(). For AG-AND
                                chips is this done by default.
                                This activates the default FLASH based bad block table functionality 
@@ -773,20 +773,6 @@ struct nand_oobinfo {
                                done according to the default builtin scheme.
                        </para>
                </sect2>
-               <sect2 id="User_space_placement_selection">
-                       <title>User space placement selection</title>
-               <para>
-                       All non ecc functions like mtd->read and mtd->write use an internal 
-                       structure, which can be set by an ioctl. This structure is preset 
-                       to the autoplacement default.
-                       <programlisting>
-       ioctl (fd, MEMSETOOBSEL, oobsel);
-                       </programlisting>
-                       oobsel is a pointer to a user supplied structure of type
-                       nand_oobconfig. The contents of this structure must match the 
-                       criteria of the filesystem, which will be used. See an example in utils/nandwrite.c.
-               </para>
-               </sect2>
        </sect1>        
        <sect1 id="Spare_area_autoplacement_default">
                <title>Spare area autoplacement default schemes</title>
@@ -1158,9 +1144,6 @@ in this page</entry>
                These constants are defined in nand.h. They are ored together to describe
                the functionality.
                <programlisting>
-/* Use a flash based bad block table. This option is parsed by the
- * default bad block table function (nand_default_bbt). */
-#define NAND_USE_FLASH_BBT     0x00010000
 /* The hw ecc generator provides a syndrome instead a ecc value on read 
  * This can only work if we have the ecc bytes directly behind the 
  * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
index 54883de5d5f9b598ab981de82269c908dec86114..ac3d0018140cd34cd7dd242334de64713406c6b6 100644 (file)
@@ -520,6 +520,11 @@ Here's a description of the fields of <varname>struct uio_mem</varname>:
 </para>
 
 <itemizedlist>
+<listitem><para>
+<varname>const char *name</varname>: Optional. Set this to help identify
+the memory region, it will show up in the corresponding sysfs node.
+</para></listitem>
+
 <listitem><para>
 <varname>int memtype</varname>: Required if the mapping is used. Set this to
 <varname>UIO_MEM_PHYS</varname> if you you have physical memory on your
@@ -553,7 +558,7 @@ instead to remember such an address.
 </itemizedlist>
 
 <para>
-Please do not touch the <varname>kobj</varname> element of
+Please do not touch the <varname>map</varname> element of
 <varname>struct uio_mem</varname>! It is used by the UIO framework
 to set up sysfs files for this mapping. Simply leave it alone.
 </para>
index 71464e09ec1841a39f031d972b281488e5d703af..b79d0a13e7cddf2512ef29069d60a54bf0399b02 100644 (file)
@@ -98,14 +98,12 @@ You must enable "SCSI tape drive support for Smart Array 5xxx" and
 "SCSI support" in your kernel configuration to be able to use SCSI
 tape drives with your Smart Array 5xxx controller.
 
-Additionally, note that the driver will not engage the SCSI core at init 
-time.  The driver must be directed to dynamically engage the SCSI core via 
-the /proc filesystem entry which the "block" side of the driver creates as 
-/proc/driver/cciss/cciss* at runtime.  This is because at driver init time, 
-the SCSI core may not yet be initialized (because the driver is a block 
-driver) and attempting to register it with the SCSI core in such a case 
-would cause a hang.  This is best done via an initialization script 
-(typically in /etc/init.d, but could vary depending on distribution). 
+Additionally, note that the driver will engage the SCSI core at init
+time if any tape drives or medium changers are detected.  The driver may
+also be directed to dynamically engage the SCSI core via the /proc filesystem
+entry which the "block" side of the driver creates as
+/proc/driver/cciss/cciss* at runtime.  This is best done via a script.
+
 For example:
 
        for x in /proc/driver/cciss/cciss[0-9]*
index c21d77742a0799424b09466857681ddcc7100f8b..7e62de1e59ff037af36728a6ec8bd3f79a822464 100644 (file)
@@ -33,9 +33,9 @@ demonstrate this problem using nested bash shells:
 
        From a second, unrelated bash shell:
        $ kill -SIGSTOP 16690
-       $ kill -SIGCONT 16990
+       $ kill -SIGCONT 16690
 
-       <at this point 16990 exits and causes 16644 to exit too>
+       <at this point 16690 exits and causes 16644 to exit too>
 
 This happens because bash can observe both signals and choose how it
 responds to them.
diff --git a/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt b/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt
new file mode 100644 (file)
index 0000000..ef66ddd
--- /dev/null
@@ -0,0 +1,14 @@
+* Atmel Data Flash
+
+Required properties:
+- compatible : "atmel,<model>", "atmel,<series>", "atmel,dataflash".
+
+Example:
+
+flash@1 {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+       spi-max-frequency = <25000000>;
+       reg = <1>;
+};
index e8552782b440af99ed14a6e851e3db5ed47d05fd..874921e97802d1d8c0e7cc2b694cca4bc3f18bf4 100644 (file)
@@ -33,6 +33,7 @@ qcom  Qualcomm, Inc.
 ramtron        Ramtron International
 samsung        Samsung Semiconductor
 schindler      Schindler
+sil    Silicon Image
 simtek
 sirf   SiRF Technology, Inc.
 stericsson     ST-Ericsson
index 64087c34327fe0ba11e790e0a41224b8e7c1d30c..7671352216f1369d8d3c7dd02f9ae06fd9f90c87 100644 (file)
@@ -63,8 +63,8 @@ IRC network.
 Userspace tools for creating and manipulating Btrfs file systems are
 available from the git repository at the following location:
 
- http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs-unstable.git
- git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs-unstable.git
+ http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs.git
+ git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs.git
 
 These include the following tools:
 
index e9890709c508b25ed9878ab979797d1fc58a7a4b..cdfe13901b99cb64a9bbc2484b13ca7cd174e878 100644 (file)
@@ -1,22 +1,24 @@
 The I2C protocol knows about two kinds of device addresses: normal 7 bit
 addresses, and an extended set of 10 bit addresses. The sets of addresses
 do not intersect: the 7 bit address 0x10 is not the same as the 10 bit
-address 0x10 (though a single device could respond to both of them). You
-select a 10 bit address by adding an extra byte after the address
-byte:
-  S Addr7 Rd/Wr ....
-becomes
-  S 11110 Addr10 Rd/Wr
-S is the start bit, Rd/Wr the read/write bit, and if you count the number
-of bits, you will see the there are 8 after the S bit for 7 bit addresses,
-and 16 after the S bit for 10 bit addresses.
+address 0x10 (though a single device could respond to both of them).
 
-WARNING! The current 10 bit address support is EXPERIMENTAL. There are
-several places in the code that will cause SEVERE PROBLEMS with 10 bit
-addresses, even though there is some basic handling and hooks. Also,
-almost no supported adapter handles the 10 bit addresses correctly.
+I2C messages to and from 10-bit address devices have a different format.
+See the I2C specification for the details.
 
-As soon as a real 10 bit address device is spotted 'in the wild', we
-can and will add proper support. Right now, 10 bit address devices
-are defined by the I2C protocol, but we have never seen a single device
-which supports them.
+The current 10 bit address support is minimal. It should work, however
+you can expect some problems along the way:
+* Not all bus drivers support 10-bit addresses. Some don't because the
+  hardware doesn't support them (SMBus doesn't require 10-bit address
+  support for example), some don't because nobody bothered adding the
+  code (or it's there but not working properly.) Software implementation
+  (i2c-algo-bit) is known to work.
+* Some optional features do not support 10-bit addresses. This is the
+  case of automatic detection and instantiation of devices by their,
+  drivers, for example.
+* Many user-space packages (for example i2c-tools) lack support for
+  10-bit addresses.
+
+Note that 10-bit address devices are still pretty rare, so the limitations
+listed above could stay for a long time, maybe even forever if nobody
+needs them to be fixed.
index cb7f3148035dbeaabbcc514ddf53705733321d66..f049a1ca186fbf6eb5e55ed9eb3a65bb8601b1f8 100644 (file)
@@ -20,7 +20,7 @@ ip_no_pmtu_disc - BOOLEAN
        default FALSE
 
 min_pmtu - INTEGER
-       default 562 - minimum discovered Path MTU
+       default 552 - minimum discovered Path MTU
 
 route/max_size - INTEGER
        Maximum number of routes allowed in the kernel.  Increase
index 646a89e0c07d50c682912ef0200dc087363cd37f..3139fb505dcec97cb609e02326110e8b5725a43a 100644 (file)
@@ -123,9 +123,10 @@ please refer directly to the source code for more information about it.
 Subsystem-Level Methods
 -----------------------
 The core methods to suspend and resume devices reside in struct dev_pm_ops
-pointed to by the pm member of struct bus_type, struct device_type and
-struct class.  They are mostly of interest to the people writing infrastructure
-for buses, like PCI or USB, or device type and device class drivers.
+pointed to by the ops member of struct dev_pm_domain, or by the pm member of
+struct bus_type, struct device_type and struct class.  They are mostly of
+interest to the people writing infrastructure for platforms and buses, like PCI
+or USB, or device type and device class drivers.
 
 Bus drivers implement these methods as appropriate for the hardware and the
 drivers using it; PCI works differently from USB, and so on.  Not many people
@@ -139,41 +140,57 @@ sequencing in the driver model tree.
 
 /sys/devices/.../power/wakeup files
 -----------------------------------
-All devices in the driver model have two flags to control handling of wakeup
-events (hardware signals that can force the device and/or system out of a low
-power state).  These flags are initialized by bus or device driver code using
+All device objects in the driver model contain fields that control the handling
+of system wakeup events (hardware signals that can force the system out of a
+sleep state).  These fields are initialized by bus or device driver code using
 device_set_wakeup_capable() and device_set_wakeup_enable(), defined in
 include/linux/pm_wakeup.h.
 
-The "can_wakeup" flag just records whether the device (and its driver) can
+The "power.can_wakeup" flag just records whether the device (and its driver) can
 physically support wakeup events.  The device_set_wakeup_capable() routine
-affects this flag.  The "should_wakeup" flag controls whether the device should
-try to use its wakeup mechanism.  device_set_wakeup_enable() affects this flag;
-for the most part drivers should not change its value.  The initial value of
-should_wakeup is supposed to be false for the majority of devices; the major
-exceptions are power buttons, keyboards, and Ethernet adapters whose WoL
-(wake-on-LAN) feature has been set up with ethtool.  It should also default
-to true for devices that don't generate wakeup requests on their own but merely
-forward wakeup requests from one bus to another (like PCI bridges).
+affects this flag.  The "power.wakeup" field is a pointer to an object of type
+struct wakeup_source used for controlling whether or not the device should use
+its system wakeup mechanism and for notifying the PM core of system wakeup
+events signaled by the device.  This object is only present for wakeup-capable
+devices (i.e. devices whose "can_wakeup" flags are set) and is created (or
+removed) by device_set_wakeup_capable().
 
 Whether or not a device is capable of issuing wakeup events is a hardware
 matter, and the kernel is responsible for keeping track of it.  By contrast,
 whether or not a wakeup-capable device should issue wakeup events is a policy
 decision, and it is managed by user space through a sysfs attribute: the
-power/wakeup file.  User space can write the strings "enabled" or "disabled" to
-set or clear the "should_wakeup" flag, respectively.  This file is only present
-for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set)
-and is created (or removed) by device_set_wakeup_capable().  Reads from the
-file will return the corresponding string.
-
-The device_may_wakeup() routine returns true only if both flags are set.
+"power/wakeup" file.  User space can write the strings "enabled" or "disabled"
+to it to indicate whether or not, respectively, the device is supposed to signal
+system wakeup.  This file is only present if the "power.wakeup" object exists
+for the given device and is created (or removed) along with that object, by
+device_set_wakeup_capable().  Reads from the file will return the corresponding
+string.
+
+The "power/wakeup" file is supposed to contain the "disabled" string initially
+for the majority of devices; the major exceptions are power buttons, keyboards,
+and Ethernet adapters whose WoL (wake-on-LAN) feature has been set up with
+ethtool.  It should also default to "enabled" for devices that don't generate
+wakeup requests on their own but merely forward wakeup requests from one bus to
+another (like PCI Express ports).
+
+The device_may_wakeup() routine returns true only if the "power.wakeup" object
+exists and the corresponding "power/wakeup" file contains the string "enabled".
 This information is used by subsystems, like the PCI bus type code, to see
 whether or not to enable the devices' wakeup mechanisms.  If device wakeup
 mechanisms are enabled or disabled directly by drivers, they also should use
 device_may_wakeup() to decide what to do during a system sleep transition.
-However for runtime power management, wakeup events should be enabled whenever
-the device and driver both support them, regardless of the should_wakeup flag.
-
+Device drivers, however, are not supposed to call device_set_wakeup_enable()
+directly in any case.
+
+It ought to be noted that system wakeup is conceptually different from "remote
+wakeup" used by runtime power management, although it may be supported by the
+same physical mechanism.  Remote wakeup is a feature allowing devices in
+low-power states to trigger specific interrupts to signal conditions in which
+they should be put into the full-power state.  Those interrupts may or may not
+be used to signal system wakeup events, depending on the hardware design.  On
+some systems it is impossible to trigger them from system sleep states.  In any
+case, remote wakeup should always be enabled for runtime power management for
+all devices and drivers that support it.
 
 /sys/devices/.../power/control files
 ------------------------------------
@@ -249,20 +266,31 @@ for every device before the next phase begins.  Not all busses or classes
 support all these callbacks and not all drivers use all the callbacks.  The
 various phases always run after tasks have been frozen and before they are
 unfrozen.  Furthermore, the *_noirq phases run at a time when IRQ handlers have
-been disabled (except for those marked with the IRQ_WAKEUP flag).
-
-All phases use bus, type, or class callbacks (that is, methods defined in
-dev->bus->pm, dev->type->pm, or dev->class->pm).  These callbacks are mutually
-exclusive, so if the device type provides a struct dev_pm_ops object pointed to
-by its pm field (i.e. both dev->type and dev->type->pm are defined), the
-callbacks included in that object (i.e. dev->type->pm) will be used.  Otherwise,
-if the class provides a struct dev_pm_ops object pointed to by its pm field
-(i.e. both dev->class and dev->class->pm are defined), the PM core will use the
-callbacks from that object (i.e. dev->class->pm).  Finally, if the pm fields of
-both the device type and class objects are NULL (or those objects do not exist),
-the callbacks provided by the bus (that is, the callbacks from dev->bus->pm)
-will be used (this allows device types to override callbacks provided by bus
-types or classes if necessary).
+been disabled (except for those marked with the IRQF_NO_SUSPEND flag).
+
+All phases use PM domain, bus, type, or class callbacks (that is, methods
+defined in dev->pm_domain->ops, dev->bus->pm, dev->type->pm, or dev->class->pm).
+These callbacks are regarded by the PM core as mutually exclusive.  Moreover,
+PM domain callbacks always take precedence over bus, type and class callbacks,
+while type callbacks take precedence over bus and class callbacks, and class
+callbacks take precedence over bus callbacks.  To be precise, the following
+rules are used to determine which callback to execute in the given phase:
+
+    1. If dev->pm_domain is present, the PM core will attempt to execute the
+       callback included in dev->pm_domain->ops.  If that callback is not
+       present, no action will be carried out for the given device.
+
+    2. Otherwise, if both dev->type and dev->type->pm are present, the callback
+       included in dev->type->pm will be executed.
+
+    3. Otherwise, if both dev->class and dev->class->pm are present, the
+       callback included in dev->class->pm will be executed.
+
+    4. Otherwise, if both dev->bus and dev->bus->pm are present, the callback
+       included in dev->bus->pm will be executed.
+
+This allows PM domains and device types to override callbacks provided by bus
+types or device classes if necessary.
 
 These callbacks may in turn invoke device- or driver-specific methods stored in
 dev->driver->pm, but they don't have to.
@@ -283,9 +311,8 @@ When the system goes into the standby or memory sleep state, the phases are:
 
        After the prepare callback method returns, no new children may be
        registered below the device.  The method may also prepare the device or
-       driver in some way for the upcoming system power transition (for
-       example, by allocating additional memory required for this purpose), but
-       it should not put the device into a low-power state.
+       driver in some way for the upcoming system power transition, but it
+       should not put the device into a low-power state.
 
     2. The suspend methods should quiesce the device to stop it from performing
        I/O.  They also may save the device registers and put it into the
index 5336149f831ba47d6215ccc1d9f9d3f66df370df..c2ae8bf77d46d6fbd12490a6a9aacc14c11c4931 100644 (file)
@@ -44,25 +44,33 @@ struct dev_pm_ops {
 };
 
 The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks
-are executed by the PM core for either the power domain, or the device type
-(if the device power domain's struct dev_pm_ops does not exist), or the class
-(if the device power domain's and type's struct dev_pm_ops object does not
-exist), or the bus type (if the device power domain's, type's and class'
-struct dev_pm_ops objects do not exist) of the given device, so the priority
-order of callbacks from high to low is that power domain callbacks, device
-type callbacks, class callbacks and bus type callbacks, and the high priority
-one will take precedence over low priority one. The bus type, device type and
-class callbacks are referred to as subsystem-level callbacks in what follows,
-and generally speaking, the power domain callbacks are used for representing
-power domains within a SoC.
+are executed by the PM core for the device's subsystem that may be either of
+the following:
+
+  1. PM domain of the device, if the device's PM domain object, dev->pm_domain,
+     is present.
+
+  2. Device type of the device, if both dev->type and dev->type->pm are present.
+
+  3. Device class of the device, if both dev->class and dev->class->pm are
+     present.
+
+  4. Bus type of the device, if both dev->bus and dev->bus->pm are present.
+
+The PM core always checks which callback to use in the order given above, so the
+priority order of callbacks from high to low is: PM domain, device type, class
+and bus type.  Moreover, the high-priority one will always take precedence over
+a low-priority one.  The PM domain, bus type, device type and class callbacks
+are referred to as subsystem-level callbacks in what follows.
 
 By default, the callbacks are always invoked in process context with interrupts
 enabled.  However, subsystems can use the pm_runtime_irq_safe() helper function
-to tell the PM core that a device's ->runtime_suspend() and ->runtime_resume()
-callbacks should be invoked in atomic context with interrupts disabled.
-This implies that these callback routines must not block or sleep, but it also
-means that the synchronous helper functions listed at the end of Section 4 can
-be used within an interrupt handler or in an atomic context.
+to tell the PM core that their ->runtime_suspend(), ->runtime_resume() and
+->runtime_idle() callbacks may be invoked in atomic context with interrupts
+disabled for a given device.  This implies that the callback routines in
+question must not block or sleep, but it also means that the synchronous helper
+functions listed at the end of Section 4 may be used for that device within an
+interrupt handler or generally in an atomic context.
 
 The subsystem-level suspend callback is _entirely_ _responsible_ for handling
 the suspend of the device as appropriate, which may, but need not include
index 079cb3df62cf6ff9908bebe493344d1cfdd99846..41c8378c0b2fb9ee86d3a781e8aaff6cad33ff9a 100644 (file)
 
        struct serial_rs485 rs485conf;
 
-       /* Set RS485 mode: */
+       /* Enable RS485 mode: */
        rs485conf.flags |= SER_RS485_ENABLED;
 
+       /* Set logical level for RTS pin equal to 1 when sending: */
+       rs485conf.flags |= SER_RS485_RTS_ON_SEND;
+       /* or, set logical level for RTS pin equal to 0 when sending: */
+       rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
+
+       /* Set logical level for RTS pin equal to 1 after sending: */
+       rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
+       /* or, set logical level for RTS pin equal to 0 after sending: */
+       rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
+
        /* Set rts delay before send, if needed: */
-       rs485conf.flags |= SER_RS485_RTS_BEFORE_SEND;
        rs485conf.delay_rts_before_send = ...;
 
        /* Set rts delay after send, if needed: */
-       rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
        rs485conf.delay_rts_after_send = ...;
 
        /* Set this flag if you want to receive data even whilst sending data */
index 4f3443230d896b92c6a5aa7b37dfd5b63e272d9b..edad99abec215d4412d139a46b5cee8a8493ca43 100644 (file)
@@ -349,6 +349,7 @@ STAC92HD83*
   ref          Reference board
   mic-ref      Reference board with power management for ports
   dell-s14     Dell laptop
+  dell-vostro-3500     Dell Vostro 3500 laptop
   hp           HP laptops with (inverted) mute-LED
   hp-dv7-4000  HP dv-7 4000
   auto         BIOS setup (default)
index 03e2771ddeef53545357cc4bfbde29a378f9206d..91fee3b45fb80f75ac406dfbba093f1f49a418c1 100644 (file)
@@ -579,7 +579,7 @@ Development Tree
 ~~~~~~~~~~~~~~~~
 The latest development codes for HD-audio are found on sound git tree:
 
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
+- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
 
 The master branch or for-next branches can be used as the main
 development branches in general while the HD-audio specific patches
@@ -594,7 +594,7 @@ is, installed via the usual spells: configure, make and make
 install(-modules).  See INSTALL in the package.  The snapshot tarballs
 are found at:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/
+- ftp://ftp.suse.com/pub/people/tiwai/snapshot/
 
 
 Sending a Bug Report
@@ -696,7 +696,7 @@ via hda-verb won't change the mixer value.
 
 The hda-verb program is found in the ftp directory:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
+- ftp://ftp.suse.com/pub/people/tiwai/misc/
 
 Also a git repository is available:
 
@@ -764,7 +764,7 @@ operation, the jack plugging simulation, etc.
 
 The package is found in:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
+- ftp://ftp.suse.com/pub/people/tiwai/misc/
 
 A git repository is available:
 
diff --git a/Kbuild b/Kbuild
index 4caab4f6cba7e951dcc751404e140a17e5781df3..b8b708ad6dc3815eb0d23bfea2c972d03b9477c0 100644 (file)
--- a/Kbuild
+++ b/Kbuild
@@ -92,7 +92,7 @@ always += missing-syscalls
 targets += missing-syscalls
 
 quiet_cmd_syscalls = CALL    $<
-      cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags)
+      cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags) $(missing_syscalls_flags)
 
 missing-syscalls: scripts/checksyscalls.sh $(offsets-file) FORCE
        $(call cmd,syscalls)
index 6388a96dc1c4acb98f167459ff3fe0670976b4eb..447560284996b3dfe8025180efdc87b1371906fd 100644 (file)
@@ -789,6 +789,7 @@ L:  linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.pengutronix.de/git/imx/linux-2.6.git
 F:     arch/arm/mach-mx*/
+F:     arch/arm/mach-imx/
 F:     arch/arm/plat-mxc/
 
 ARM/FREESCALE IMX51
@@ -804,6 +805,13 @@ S: Maintained
 T:     git git://git.linaro.org/people/shawnguo/linux-2.6.git
 F:     arch/arm/mach-imx/*imx6*
 
+ARM/FREESCALE MXS ARM ARCHITECTURE
+M:     Shawn Guo <shawn.guo@linaro.org>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+T:     git git://git.linaro.org/people/shawnguo/linux-2.6.git
+F:     arch/arm/mach-mxs/
+
 ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1032,6 +1040,7 @@ F:        arch/arm/include/asm/hardware/ioc.h
 F:     arch/arm/include/asm/hardware/iomd.h
 F:     arch/arm/include/asm/hardware/memc.h
 F:     arch/arm/mach-rpc/
+F:     drivers/net/ethernet/8390/etherh.c
 F:     drivers/net/ethernet/i825xx/ether1*
 F:     drivers/net/ethernet/seeq/ether3*
 F:     drivers/scsi/arm/
@@ -1105,6 +1114,7 @@ F:        drivers/media/video/s5p-fimc/
 ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 M:     Kamil Debski <k.debski@samsung.com>
+M:     Jeongtae Park <jtp.park@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
 S:     Maintained
@@ -1787,6 +1797,14 @@ F:       include/net/cfg80211.h
 F:     net/wireless/*
 X:     net/wireless/wext*
 
+CHAR and MISC DRIVERS
+M:     Arnd Bergmann <arnd@arndb.de>
+M:     Greg Kroah-Hartman <greg@kroah.com>
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
+S:     Maintained
+F:     drivers/char/*
+F:     drivers/misc/*
+
 CHECKPATCH
 M:     Andy Whitcroft <apw@canonical.com>
 S:     Supported
@@ -1925,9 +1943,11 @@ S:       Maintained
 F:     drivers/connector/
 
 CONTROL GROUPS (CGROUPS)
-M:     Paul Menage <paul@paulmenage.org>
+M:     Tejun Heo <tj@kernel.org>
 M:     Li Zefan <lizf@cn.fujitsu.com>
 L:     containers@lists.linux-foundation.org
+L:     cgroups@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
 S:     Maintained
 F:     include/linux/cgroup*
 F:     kernel/cgroup*
@@ -2341,6 +2361,13 @@ S:       Supported
 F:     drivers/gpu/drm/i915
 F:     include/drm/i915*
 
+DRM DRIVERS FOR EXYNOS
+M:     Inki Dae <inki.dae@samsung.com>
+L:     dri-devel@lists.freedesktop.org
+S:     Supported
+F:     drivers/gpu/drm/exynos
+F:     include/drm/exynos*
+
 DSCC4 DRIVER
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
@@ -2575,7 +2602,7 @@ S:        Maintained
 F:     drivers/net/ethernet/i825xx/eexpress.*
 
 ETHERNET BRIDGE
-M:     Stephen Hemminger <shemminger@linux-foundation.org>
+M:     Stephen Hemminger <shemminger@vyatta.com>
 L:     bridge@lists.linux-foundation.org
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net:Bridge
@@ -3709,7 +3736,7 @@ F:        fs/jbd2/
 F:     include/linux/jbd2.h
 
 JSM Neo PCI based serial card
-M:     Breno Leitao <leitao@linux.vnet.ibm.com>
+M:     Lucas Tavares <lucaskt@linux.vnet.ibm.com>
 L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/tty/serial/jsm/
@@ -4295,6 +4322,7 @@ MEMORY RESOURCE CONTROLLER
 M:     Balbir Singh <bsingharora@gmail.com>
 M:     Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
 M:     KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+L:     cgroups@vger.kernel.org
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/memcontrol.c
@@ -4328,7 +4356,7 @@ MIPS
 M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-mips@linux-mips.org
 W:     http://www.linux-mips.org/
-T:     git git://git.linux-mips.org/pub/scm/linux.git
+T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
 Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
 S:     Supported
 F:     Documentation/mips/
@@ -4461,7 +4489,7 @@ S:        Supported
 F:     drivers/infiniband/hw/nes/
 
 NETEM NETWORK EMULATOR
-M:     Stephen Hemminger <shemminger@linux-foundation.org>
+M:     Stephen Hemminger <shemminger@vyatta.com>
 L:     netem@lists.linux-foundation.org
 S:     Maintained
 F:     net/sched/sch_netem.c
@@ -4672,7 +4700,7 @@ L:        linux-omap@vger.kernel.org
 W:     http://www.muru.com/linux/omap/
 W:     http://linux.omap.com/
 Q:     http://patchwork.kernel.org/project/linux-omap/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
 S:     Maintained
 F:     arch/arm/*omap*/
 
@@ -4938,7 +4966,7 @@ F:        drivers/char/ppdev.c
 F:     include/linux/ppdev.h
 
 PARAVIRT_OPS INTERFACE
-M:     Jeremy Fitzhardinge <jeremy@xensource.com>
+M:     Jeremy Fitzhardinge <jeremy@goop.org>
 M:     Chris Wright <chrisw@sous-sol.org>
 M:     Alok Kataria <akataria@vmware.com>
 M:     Rusty Russell <rusty@rustcorp.com.au>
@@ -5470,7 +5498,7 @@ S:        Maintained
 F:     drivers/net/ethernet/rdc/r6040.c
 
 RDS - RELIABLE DATAGRAM SOCKETS
-M:     Andy Grover <andy.grover@oracle.com>
+M:     Venkat Venkatsubra <venkat.x.venkatsubra@oracle.com>
 L:     rds-devel@oss.oracle.com (moderated for non-subscribers)
 S:     Supported
 F:     net/rds/
@@ -5647,7 +5675,6 @@ F:        drivers/media/video/*7146*
 F:     include/media/*7146*
 
 SAMSUNG AUDIO (ASoC) DRIVERS
-M:     Jassi Brar <jassisinghbrar@gmail.com>
 M:     Sangbeom Kim <sbkim73@samsung.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
@@ -5976,7 +6003,7 @@ S:        Maintained
 F:     drivers/usb/misc/sisusbvga/
 
 SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
-M:     Stephen Hemminger <shemminger@linux-foundation.org>
+M:     Stephen Hemminger <shemminger@vyatta.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/marvell/sk*
@@ -6121,7 +6148,7 @@ F:        sound/
 SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
 M:     Liam Girdwood <lrg@ti.com>
 M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:     http://alsa-project.org/main/index.php/ASoC
 S:     Supported
@@ -7390,8 +7417,8 @@ S:        Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
 
 XEN HYPERVISOR INTERFACE
-M:     Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
 M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+M:     Jeremy Fitzhardinge <jeremy@goop.org>
 L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
 L:     virtualization@lists.linux-foundation.org
 S:     Supported
@@ -7424,7 +7451,8 @@ F:        drivers/xen/*swiotlb*
 
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
-M:     Alex Elder <aelder@sgi.com>
+M:     Ben Myers <bpm@sgi.com>
+M:     Alex Elder <elder@kernel.org>
 M:     xfs-masters@oss.sgi.com
 L:     xfs@oss.sgi.com
 W:     http://oss.sgi.com/projects/xfs
index ed25c5b35470dc2035f8b024994fa6cb7cecaca6..12aafc20efbd0d610430d3a88df4e6359093cfc1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
-PATCHLEVEL = 1
+PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION =
-NAME = "Divemaster Edition"
+EXTRAVERSION = -rc4
+NAME = Saber-toothed Squirrel
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 57e16d4e14dcc6ff495a5c5d73a2539869360211..96804b5dd21b002b5a1ff13b7ea0b2c09dbe5e61 100644 (file)
@@ -1233,7 +1233,7 @@ config ARM_ERRATA_742231
          capabilities of the processor.
 
 config PL310_ERRATA_588369
-       bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
+       bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
        depends on CACHE_L2X0
        help
           The PL310 L2 cache controller implements three types of Clean &
@@ -1258,7 +1258,7 @@ config ARM_ERRATA_720789
          entries regardless of the ASID.
 
 config PL310_ERRATA_727915
-       bool "Background Clean & Invalidate by Way operation can cause data corruption"
+       bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
        depends on CACHE_L2X0
        help
          PL310 implements the Clean & Invalidate by Way L2 cache maintenance
@@ -1291,8 +1291,8 @@ config ARM_ERRATA_751472
          operation is received by a CPU before the ICIALLUIS has completed,
          potentially leading to corrupted entries in the cache or TLB.
 
-config ARM_ERRATA_753970
-       bool "ARM errata: cache sync operation may be faulty"
+config PL310_ERRATA_753970
+       bool "PL310 errata: cache sync operation may be faulty"
        depends on CACHE_PL310
        help
          This option enables the workaround for the 753970 PL310 (r3p0) erratum.
@@ -1354,6 +1354,18 @@ config ARM_ERRATA_764369
          relevant cache maintenance functions and sets a specific bit
          in the diagnostic control register of the SCU.
 
+config PL310_ERRATA_769419
+       bool "PL310 errata: no automatic Store Buffer drain"
+       depends on CACHE_L2X0
+       help
+         On revisions of the PL310 prior to r3p2, the Store Buffer does
+         not automatically drain. This can cause normal, non-cacheable
+         writes to be retained when the memory system is idle, leading
+         to suboptimal I/O performance for drivers using coherent DMA.
+         This option adds a write barrier to the cpu_idle loop so that,
+         on systems with an outer cache, the store buffer is drained
+         explicitly.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
index 176062ac7f07305014357372c42285ff07a09c68..5df26a9976a26c10ddfcf0f788302dd2caeb8769 100644 (file)
@@ -65,6 +65,8 @@ $(obj)/%.dtb: $(src)/dts/%.dts
 
 $(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
 
+clean-files := *.dtb
+
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
                   -C none -a $(LOADADDR) -e $(STARTADDR) \
index 9b29a623aaf1a4296d45fb8c45c835466617619c..3f9abd6b6964546014490a3942abce3675e6e254 100644 (file)
        sdhci@c8000400 {
                cd-gpios = <&gpio 69 0>; /* gpio PI5 */
                wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-               power-gpios = <&gpio 155 0>; /* gpio PT3 */
+               power-gpios = <&gpio 70 0>; /* gpio PI6 */
        };
 
        sdhci@c8000600 {
-               power-gpios = <&gpio 70 0>; /* gpio PI6 */
                support-8bit;
        };
 };
index 0e6ae470c94f26589c0721a059dfaded9b2f30b1..410a546060a2eecf82859d76c528223e8796f9f4 100644 (file)
@@ -526,7 +526,8 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
                sizeof(u32));
        BUG_ON(!gic->saved_ppi_conf);
 
-       cpu_pm_register_notifier(&gic_notifier_block);
+       if (gic == &gic_data[0])
+               cpu_pm_register_notifier(&gic_notifier_block);
 }
 #else
 static void __init gic_pm_init(struct gic_chip_data *gic)
@@ -581,13 +582,16 @@ void __init gic_init(unsigned int gic_nr, int irq_start,
         * For primary GICs, skip over SGIs.
         * For secondary GICs, skip over PPIs, too.
         */
+       domain->hwirq_base = 32;
        if (gic_nr == 0) {
                gic_cpu_base_addr = cpu_base;
-               domain->hwirq_base = 16;
-               if (irq_start > 0)
-                       irq_start = (irq_start & ~31) + 16;
-       } else
-               domain->hwirq_base = 32;
+
+               if ((irq_start & 31) > 0) {
+                       domain->hwirq_base = 16;
+                       if (irq_start != -1)
+                               irq_start = (irq_start & ~31) + 16;
+               }
+       }
 
        /*
         * Find out how many interrupts are supported.
index 7129cfbdacd6887920cf28994625be7b35f65503..f407a6b35d3dd1e6ad1e72afec38837dcfdd796a 100644 (file)
@@ -1211,8 +1211,8 @@ static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc)
        ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT);
        ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT);
 
-       ccr |= (rqc->dcctl << CC_SRCCCTRL_SHFT);
-       ccr |= (rqc->scctl << CC_DSTCCTRL_SHFT);
+       ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT);
+       ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT);
 
        ccr |= (rqc->swap << CC_SWAP_SHFT);
 
@@ -1623,6 +1623,11 @@ static inline int _alloc_event(struct pl330_thread *thrd)
        return -1;
 }
 
+static bool _chan_ns(const struct pl330_info *pi, int i)
+{
+       return pi->pcfg.irq_ns & (1 << i);
+}
+
 /* Upon success, returns IdentityToken for the
  * allocated channel, NULL otherwise.
  */
@@ -1647,7 +1652,8 @@ void *pl330_request_channel(const struct pl330_info *pi)
 
        for (i = 0; i < chans; i++) {
                thrd = &pl330->channels[i];
-               if (thrd->free) {
+               if ((thrd->free) && (!_manager_ns(thrd) ||
+                                       _chan_ns(pi, i))) {
                        thrd->ev = _alloc_event(thrd);
                        if (thrd->ev >= 0) {
                                thrd->free = false;
diff --git a/arch/arm/configs/at91cap9_defconfig b/arch/arm/configs/at91cap9_defconfig
new file mode 100644 (file)
index 0000000..8826eb2
--- /dev/null
@@ -0,0 +1,108 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91CAP9=y
+CONFIG_MACH_AT91CAP9ADK=y
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/at91cap9adk_defconfig b/arch/arm/configs/at91cap9adk_defconfig
deleted file mode 100644 (file)
index ffb1edd..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91CAP9=y
-CONFIG_MACH_AT91CAP9ADK=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
index 38cb7c98542623a92cc7791a89f701e9fe5adf48..bbe4e1a1f5d86f81464e393e2fd2ab228e34542c 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
@@ -56,7 +55,6 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -75,18 +73,8 @@ CONFIG_IPV6_TUNNEL=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
 CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_AFS_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -108,8 +96,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
-CONFIG_EEPROM_LEGACY=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
@@ -119,14 +105,23 @@ CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
+CONFIG_ARM_AT91_ETHER=y
 CONFIG_PHYLIB=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_SMSC_PHY=y
 CONFIG_MICREL_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=y
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_USB_CATC=m
 CONFIG_USB_KAWETH=m
 CONFIG_USB_PEGASUS=m
@@ -139,18 +134,6 @@ CONFIG_USB_NET_RNDIS_HOST=m
 CONFIG_USB_ALI_M5632=y
 CONFIG_USB_AN2720=y
 CONFIG_USB_EPSON2888=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
@@ -158,9 +141,9 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_LEGACY_PTY_COUNT=32
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=32
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -290,7 +273,6 @@ CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
@@ -335,7 +317,6 @@ CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 CONFIG_CRYPTO_PCBC=y
 CONFIG_CRYPTO_SHA1=y
diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig
new file mode 100644 (file)
index 0000000..505b376
--- /dev/null
@@ -0,0 +1,91 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9260=y
+CONFIG_ARCH_AT91SAM9260_SAM9XE=y
+CONFIG_MACH_AT91SAM9260EK=y
+CONFIG_MACH_CAM60=y
+CONFIG_MACH_SAM9_L9260=y
+CONFIG_MACH_AFEB9260=y
+CONFIG_MACH_USB_A9260=y
+CONFIG_MACH_QIL_A9260=y
+CONFIG_MACH_CPU9260=y
+CONFIG_MACH_FLEXIBITY=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
deleted file mode 100644 (file)
index f8a9226..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_AT91SAM9260EK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig
new file mode 100644 (file)
index 0000000..9123568
--- /dev/null
@@ -0,0 +1,124 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G20=y
+CONFIG_MACH_AT91SAM9G20EK=y
+CONFIG_MACH_AT91SAM9G20EK_2MMC=y
+CONFIG_MACH_CPU9G20=y
+CONFIG_MACH_ACMENETUSFOXG20=y
+CONFIG_MACH_PORTUXG20=y
+CONFIG_MACH_STAMP9G20=y
+CONFIG_MACH_PCONTROL_G20=y
+CONFIG_MACH_GSIA18S=y
+CONFIG_MACH_USB_A9G20=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_SPIDEV=y
+# CONFIG_HWMON is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
diff --git a/arch/arm/configs/at91sam9g20ek_defconfig b/arch/arm/configs/at91sam9g20ek_defconfig
deleted file mode 100644 (file)
index 9e90e6d..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9G20=y
-CONFIG_MACH_AT91SAM9G20EK=y
-CONFIG_MACH_AT91SAM9G20EK_2MMC=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
-CONFIG_HW_RANDOM=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_SPI_SPIDEV=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PROCFS is not set
-CONFIG_SND_AT73C213=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
index c5876d244f4b2d667db3d4753bdc1bdab1203064..606d48f3b8f81c10370b718d7b2b3475818b9a03 100644 (file)
@@ -18,6 +18,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_AT91=y
 CONFIG_ARCH_AT91SAM9G45=y
 CONFIG_MACH_AT91SAM9M10G45EK=y
+CONFIG_MACH_AT91SAM_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 CONFIG_AT91_SLOW_CLOCK=y
 CONFIG_AEABI=y
@@ -73,11 +74,8 @@ CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_MII=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_DAVICOM_PHY=y
 CONFIG_LIBERTAS_THINFIRM=m
 CONFIG_LIBERTAS_THINFIRM_USB=m
 CONFIG_AT76C50X_USB=m
@@ -131,7 +129,6 @@ CONFIG_I2C_GPIO=y
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 # CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
 CONFIG_FB=y
 CONFIG_FB_ATMEL=y
 CONFIG_FB_UDL=m
diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig
new file mode 100644 (file)
index 0000000..ad562ee
--- /dev/null
@@ -0,0 +1,79 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9RL=y
+CONFIG_MACH_AT91SAM9RLEK=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=24576
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91sam9rlek_defconfig b/arch/arm/configs/at91sam9rlek_defconfig
deleted file mode 100644 (file)
index 75621e4..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9RL=y
-CONFIG_MACH_AT91SAM9RLEK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=4
-CONFIG_BLK_DEV_RAM_SIZE=24576
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
index 227a477346edb44a2a83ba49a0f9b7cd2b165ec0..d95763d5f0d83df6543364e3ea648c2ad88994bf 100644 (file)
@@ -287,7 +287,7 @@ CONFIG_USB=y
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
index 176ec22af0342f215b59a2778144d69ef0f4c806..fd996bb13022879dee93c308c8e8ad154918ec20 100644 (file)
@@ -263,7 +263,7 @@ CONFIG_USB=y
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
index a88e64d4e9a5862c28160c9d1b7d3cd01edf0550..443675d317e6de326c576caf47ae9ff179a0814c 100644 (file)
@@ -132,7 +132,7 @@ CONFIG_USB_MON=m
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_USB_GADGETFS=m
index 7b63462b349d7de9965b13bec7c1c85e57c25fcd..a7e77758137881bf52067b145ae220f0447b7fdc 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_MACH_SX1=y
 CONFIG_MACH_NOKIA770=y
 CONFIG_MACH_AMS_DELTA=y
 CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
 CONFIG_OMAP_ARM_216MHZ=y
 CONFIG_OMAP_ARM_195MHZ=y
 CONFIG_OMAP_ARM_192MHZ=y
index 4a5a12681be2038c908318ffc953c3ad7a9bd431..374000ec4e4e9a66bbf07304abd75dced85a0b66 100644 (file)
@@ -14,8 +14,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_U300=y
 CONFIG_MACH_U300=y
 CONFIG_MACH_U300_BS335=y
-CONFIG_MACH_U300_DUAL_RAM=y
-CONFIG_U300_DEBUG=y
 CONFIG_MACH_U300_SPIDUMMY=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -26,19 +24,21 @@ CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072"
 CONFIG_CPU_IDLE=y
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 # CONFIG_SUSPEND is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_MISC_DEVICES is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_HWMON is not set
@@ -51,6 +51,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
@@ -65,10 +66,8 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRC32 is not set
index 97d31a4663daf0c6186cd948a05abf35687686d3..2d7b6e7b72713cba72df0349462c29dbe38a67ba 100644 (file)
@@ -10,7 +10,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_U8500=y
 CONFIG_UX500_SOC_DB5500=y
 CONFIG_UX500_SOC_DB8500=y
-CONFIG_MACH_U8500=y
+CONFIG_MACH_HREFV60=y
 CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_U5500=y
 CONFIG_NO_HZ=y
@@ -24,6 +24,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -41,11 +42,8 @@ CONFIG_MISC_DEVICES=y
 CONFIG_AB8500_PWM=y
 CONFIG_SENSORS_BH1780=y
 CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_SMSC_PHY=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
@@ -72,15 +70,12 @@ CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_TC3589X=y
-# CONFIG_HWMON is not set
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
+CONFIG_AB5500_CORE=y
 CONFIG_AB8500_CORE=y
 CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-CONFIG_MUSB_PIO_ONLY=y
 CONFIG_USB_GADGET=y
 CONFIG_AB8500_USB=y
 CONFIG_MMC=y
@@ -97,6 +92,7 @@ CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
 CONFIG_STAGING=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
+CONFIG_HSEM_U8500=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
index 59577ad3f4efdfda65e65753054673a32614e80f..547a3c1e59dbcd88ea9da77505691110508f9daf 100644 (file)
@@ -140,7 +140,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_GADGET=m
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
index 1db1143a94838cb92419040c40009f17d1ee2f97..7df239bcdf2745b6a3d20e5a90ed3bac27d73ecc 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __ASM_ARM_HARDWARE_L2X0_H
 #define __ASM_ARM_HARDWARE_L2X0_H
 
+#include <linux/errno.h>
+
 #define L2X0_CACHE_ID                  0x000
 #define L2X0_CACHE_TYPE                        0x004
 #define L2X0_CTRL                      0x100
index 7d19425dd496a083eb98557bafe2980843bc9fa3..2b0efc3104ac6f73846fb89cdf0761c400676540 100644 (file)
@@ -13,6 +13,7 @@
 struct tag;
 struct meminfo;
 struct sys_timer;
+struct pt_regs;
 
 struct machine_desc {
        unsigned int            nr;             /* architecture number  */
index 71d99b83cdb980178aac275e487c2db081c041fc..0bda22c094a6dd1b70100444d6e29fa1a41688ef 100644 (file)
@@ -55,16 +55,6 @@ reserve_pmu(enum arm_pmu_type type);
 extern void
 release_pmu(enum arm_pmu_type type);
 
-/**
- * init_pmu() - Initialise the PMU.
- *
- * Initialise the system ready for PMU enabling. This should typically set the
- * IRQ affinity and nothing else. The users (oprofile/perf events etc) will do
- * the actual hardware initialisation.
- */
-extern int
-init_pmu(enum arm_pmu_type type);
-
 #else /* CONFIG_CPU_HAS_PMU */
 
 #include <linux/err.h>
index a7e457ed27c31e1185ebe3a0eaa745d88c35029d..58b8b84adcd2cf5f295e6869b68350f9dcadc798 100644 (file)
@@ -25,7 +25,7 @@ extern struct cputopo_arm cpu_topology[NR_CPUS];
 
 void init_cpu_topology(void);
 void store_cpu_topology(unsigned int cpuid);
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
+const struct cpumask *cpu_coregroup_mask(int cpu);
 
 #else
 
index c60a2944f95b82a0cc9d5bfea32d88c65ecb202f..4a1123783806b79ef559ed51a093353feb67070e 100644 (file)
 #define __NR_syncfs                    (__NR_SYSCALL_BASE+373)
 #define __NR_sendmmsg                  (__NR_SYSCALL_BASE+374)
 #define __NR_setns                     (__NR_SYSCALL_BASE+375)
+#define __NR_process_vm_readv          (__NR_SYSCALL_BASE+376)
+#define __NR_process_vm_writev         (__NR_SYSCALL_BASE+377)
 
 /*
  * The following SWIs are ARM private.
index 9943e9e74a1bda0b17bc6e1ee93ca3ab2b80f970..463ff4a0ec8acaa69372b8abd40a39260ee91736 100644 (file)
                CALL(sys_syncfs)
                CALL(sys_sendmmsg)
 /* 375 */      CALL(sys_setns)
+               CALL(sys_process_vm_readv)
+               CALL(sys_process_vm_writev)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index 9ad50c4208aebf5aaf7ee245444da5789935b269..b145f16c91bc786db82fcd3cd66ccdee7b740aa4 100644 (file)
@@ -497,7 +497,7 @@ ENDPROC(__und_usr)
        .popsection
        .pushsection __ex_table,"a"
        .long   1b, 4b
-#if __LINUX_ARM_ARCH__ >= 7
+#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
        .long   2b, 4b
        .long   3b, 4b
 #endif
index 566c54c2a1fef28bffea090e89bcec998b73ede6..08c82fd844a8683533216048b54ff2f210729fb6 100644 (file)
@@ -360,7 +360,7 @@ __secondary_data:
  *  r13 = *virtual* address to jump to upon completion
  */
 __enable_mmu:
-#ifdef CONFIG_ALIGNMENT_TRAP
+#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
        orr     r0, r0, #CR_A
 #else
        bic     r0, r0, #CR_A
index 9fe8910308af922eda3c17ffee908c99652c1a1f..8a30c89da70ec104d4c1499f3a88a1dc4721e6e0 100644 (file)
@@ -519,10 +519,12 @@ static const union decode_item arm_cccc_0000_____1001_table[] = {
 static const union decode_item arm_cccc_0001_____1001_table[] = {
        /* Synchronization primitives                                   */
 
+#if __LINUX_ARM_ARCH__ < 6
+       /* Deprecated on ARMv6 and may be UNDEFINED on v7               */
        /* SMP/SWPB             cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
        DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
                                                 REGS(NOPC, NOPC, 0, 0, NOPC)),
-
+#endif
        /* LDREX/STREX{,D,B,H}  cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
        /* And unallocated instructions...                              */
        DECODE_END
index fc82de8bdcce1081801cece62fa3d97480d520e1..ba32b393b3f0c514c83799687348d52655bfe1da 100644 (file)
@@ -427,18 +427,25 @@ void kprobe_arm_test_cases(void)
 
        TEST_GROUP("Synchronization primitives")
 
-       /*
-        * Use hard coded constants for SWP instructions to avoid warnings
-        * about deprecated instructions.
-        */
-       TEST_RP( ".word 0xe108e097 @ swp        lr, r",7,VAL2,", [r",8,0,"]")
-       TEST_R(  ".word 0x610d0091 @ swpvs      r0, r",1,VAL1,", [sp]")
-       TEST_RP( ".word 0xe10cd09e @ swp        sp, r",14,VAL2,", [r",12,13*4,"]")
+#if __LINUX_ARM_ARCH__ < 6
+       TEST_RP("swp    lr, r",7,VAL2,", [r",8,0,"]")
+       TEST_R( "swpvs  r0, r",1,VAL1,", [sp]")
+       TEST_RP("swp    sp, r",14,VAL2,", [r",12,13*4,"]")
+#else
+       TEST_UNSUPPORTED(".word 0xe108e097 @ swp        lr, r7, [r8]")
+       TEST_UNSUPPORTED(".word 0x610d0091 @ swpvs      r0, r1, [sp]")
+       TEST_UNSUPPORTED(".word 0xe10cd09e @ swp        sp, r14 [r12]")
+#endif
        TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]")
        TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]")
        TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]")
-       TEST_RP( ".word 0xe148e097 @ swpb       lr, r",7,VAL2,", [r",8,0,"]")
-       TEST_R(  ".word 0x614d0091 @ swpvsb     r0, r",1,VAL1,", [sp]")
+#if __LINUX_ARM_ARCH__ < 6
+       TEST_RP("swpb   lr, r",7,VAL2,", [r",8,0,"]")
+       TEST_R( "swpvsb r0, r",1,VAL1,", [sp]")
+#else
+       TEST_UNSUPPORTED(".word 0xe148e097 @ swpb       lr, r7, [r8]")
+       TEST_UNSUPPORTED(".word 0x614d0091 @ swpvsb     r0, r1, [sp]")
+#endif
        TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]")
 
        TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */
@@ -550,7 +557,7 @@ void kprobe_arm_test_cases(void)
        TEST_RPR(  "strccd      r",8, VAL2,", [r",13,0, ", r",12,48,"]")
        TEST_RPR(  "strd        r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
        TEST_RPR(  "strcsd      r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
-       TEST_RPR(  "strd        r",2, VAL1,", [r",3, 24,"], r",4,48,"")
+       TEST_RPR(  "strd        r",2, VAL1,", [r",5, 24,"], r",4,48,"")
        TEST_RPR(  "strd        r",10,VAL2,", [r",9, 48,"], -r",7,24,"")
        TEST_UNSUPPORTED(".word 0xe1afc0fa      @ strd r12, [pc, r10]!")
 
index 5e726c31c45aef5084a7e7ddf07bb1762ed4c403..5d8b857922220b4be4e9babf6e050c94625a56eb 100644 (file)
@@ -222,8 +222,8 @@ void kprobe_thumb16_test_cases(void)
 DONT_TEST_IN_ITBLOCK(
        TEST_BF_R(  "cbnz       r",0,0, ", 2f")
        TEST_BF_R(  "cbz        r",2,-1,", 2f")
-       TEST_BF_RX( "cbnz       r",4,1, ", 2f",0x20)
-       TEST_BF_RX( "cbz        r",7,0, ", 2f",0x40)
+       TEST_BF_RX( "cbnz       r",4,1, ", 2f", SPACE_0x20)
+       TEST_BF_RX( "cbz        r",7,0, ", 2f", SPACE_0x40)
 )
        TEST_R("sxth    r0, r",7, HH1,"")
        TEST_R("sxth    r7, r",0, HH2,"")
@@ -246,7 +246,7 @@ DONT_TEST_IN_ITBLOCK(
        TESTCASE_START(code)            \
        TEST_ARG_PTR(13, offset)        \
        TEST_ARG_END("")                \
-       TEST_BRANCH_F(code,0)           \
+       TEST_BRANCH_F(code)             \
        TESTCASE_END
 
        TEST("push      {r0}")
@@ -319,8 +319,8 @@ CONDITION_INSTRUCTIONS(8,
 
        TEST_BF(  "b    2f")
        TEST_BB(  "b    2b")
-       TEST_BF_X("b    2f", 0x400)
-       TEST_BB_X("b    2b", 0x400)
+       TEST_BF_X("b    2f", SPACE_0x400)
+       TEST_BB_X("b    2b", SPACE_0x400)
 
        TEST_GROUP("Testing instructions in IT blocks")
 
@@ -746,7 +746,7 @@ CONDITION_INSTRUCTIONS(22,
        TEST_BB("bne.w  2b")
        TEST_BF("bgt.w  2f")
        TEST_BB("blt.w  2b")
-       TEST_BF_X("bpl.w        2f",0x1000)
+       TEST_BF_X("bpl.w        2f", SPACE_0x1000)
 )
 
        TEST_UNSUPPORTED("msr   cpsr, r0")
@@ -786,11 +786,11 @@ CONDITION_INSTRUCTIONS(22,
 
        TEST_BF(  "b.w  2f")
        TEST_BB(  "b.w  2b")
-       TEST_BF_X("b.w  2f", 0x1000)
+       TEST_BF_X("b.w  2f", SPACE_0x1000)
 
        TEST_BF(  "bl.w 2f")
        TEST_BB(  "bl.w 2b")
-       TEST_BB_X("bl.w 2b", 0x1000)
+       TEST_BB_X("bl.w 2b", SPACE_0x1000)
 
        TEST_X( "blx    __dummy_arm_subroutine",
                ".arm                           \n\t"
index 0dc5d77b9356bcd86b4b0c087bf642bc6396e06e..e28a869b1ae4b7be5abfb7d088c3214bfe2caab7 100644 (file)
@@ -149,23 +149,31 @@ struct test_arg_end {
        "1:     "instruction"                           \n\t"   \
        "       nop                                     \n\t"
 
-#define TEST_BRANCH_F(instruction, xtra_dist)                  \
+#define TEST_BRANCH_F(instruction)                             \
        TEST_INSTRUCTION(instruction)                           \
-       ".if "#xtra_dist"                               \n\t"   \
        "       b       99f                             \n\t"   \
-       ".space "#xtra_dist"                            \n\t"   \
-       ".endif                                         \n\t"   \
+       "2:     nop                                     \n\t"
+
+#define TEST_BRANCH_B(instruction)                             \
+       "       b       50f                             \n\t"   \
+       "       b       99f                             \n\t"   \
+       "2:     nop                                     \n\t"   \
+       "       b       99f                             \n\t"   \
+       TEST_INSTRUCTION(instruction)
+
+#define TEST_BRANCH_FX(instruction, codex)                     \
+       TEST_INSTRUCTION(instruction)                           \
+       "       b       99f                             \n\t"   \
+       codex"                                          \n\t"   \
        "       b       99f                             \n\t"   \
        "2:     nop                                     \n\t"
 
-#define TEST_BRANCH_B(instruction, xtra_dist)                  \
+#define TEST_BRANCH_BX(instruction, codex)                     \
        "       b       50f                             \n\t"   \
        "       b       99f                             \n\t"   \
        "2:     nop                                     \n\t"   \
        "       b       99f                             \n\t"   \
-       ".if "#xtra_dist"                               \n\t"   \
-       ".space "#xtra_dist"                            \n\t"   \
-       ".endif                                         \n\t"   \
+       codex"                                          \n\t"   \
        TEST_INSTRUCTION(instruction)
 
 #define TESTCASE_END                                           \
@@ -301,47 +309,60 @@ struct test_arg_end {
        TESTCASE_START(code1 #reg1 code2)       \
        TEST_ARG_PTR(reg1, val1)                \
        TEST_ARG_END("")                        \
-       TEST_BRANCH_F(code1 #reg1 code2, 0)     \
+       TEST_BRANCH_F(code1 #reg1 code2)        \
        TESTCASE_END
 
-#define TEST_BF_X(code, xtra_dist)             \
+#define TEST_BF(code)                          \
        TESTCASE_START(code)                    \
        TEST_ARG_END("")                        \
-       TEST_BRANCH_F(code, xtra_dist)          \
+       TEST_BRANCH_F(code)                     \
        TESTCASE_END
 
-#define TEST_BB_X(code, xtra_dist)             \
+#define TEST_BB(code)                          \
        TESTCASE_START(code)                    \
        TEST_ARG_END("")                        \
-       TEST_BRANCH_B(code, xtra_dist)          \
+       TEST_BRANCH_B(code)                     \
        TESTCASE_END
 
-#define TEST_BF_RX(code1, reg, val, code2, xtra_dist)  \
-       TESTCASE_START(code1 #reg code2)                \
-       TEST_ARG_REG(reg, val)                          \
-       TEST_ARG_END("")                                \
-       TEST_BRANCH_F(code1 #reg code2, xtra_dist)      \
+#define TEST_BF_R(code1, reg, val, code2)      \
+       TESTCASE_START(code1 #reg code2)        \
+       TEST_ARG_REG(reg, val)                  \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_F(code1 #reg code2)         \
        TESTCASE_END
 
-#define TEST_BB_RX(code1, reg, val, code2, xtra_dist)  \
-       TESTCASE_START(code1 #reg code2)                \
-       TEST_ARG_REG(reg, val)                          \
-       TEST_ARG_END("")                                \
-       TEST_BRANCH_B(code1 #reg code2, xtra_dist)      \
+#define TEST_BB_R(code1, reg, val, code2)      \
+       TESTCASE_START(code1 #reg code2)        \
+       TEST_ARG_REG(reg, val)                  \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_B(code1 #reg code2)         \
        TESTCASE_END
 
-#define TEST_BF(code)  TEST_BF_X(code, 0)
-#define TEST_BB(code)  TEST_BB_X(code, 0)
-
-#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0)
-#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0)
-
 #define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3)        \
        TESTCASE_START(code1 #reg1 code2 #reg2 code3)           \
        TEST_ARG_REG(reg1, val1)                                \
        TEST_ARG_REG(reg2, val2)                                \
        TEST_ARG_END("")                                        \
-       TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0)         \
+       TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3)            \
+       TESTCASE_END
+
+#define TEST_BF_X(code, codex)                 \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_FX(code, codex)             \
+       TESTCASE_END
+
+#define TEST_BB_X(code, codex)                 \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_BX(code, codex)             \
+       TESTCASE_END
+
+#define TEST_BF_RX(code1, reg, val, code2, codex)      \
+       TESTCASE_START(code1 #reg code2)                \
+       TEST_ARG_REG(reg, val)                          \
+       TEST_ARG_END("")                                \
+       TEST_BRANCH_FX(code1 #reg code2, codex)         \
        TESTCASE_END
 
 #define TEST_X(code, codex)                    \
@@ -372,6 +393,25 @@ struct test_arg_end {
        TESTCASE_END
 
 
+/*
+ * Macros for defining space directives spread over multiple lines.
+ * These are required so the compiler guesses better the length of inline asm
+ * code and will spill the literal pool early enough to avoid generating PC
+ * relative loads with out of range offsets.
+ */
+#define TWICE(x)       x x
+#define SPACE_0x8      TWICE(".space 4\n\t")
+#define SPACE_0x10     TWICE(SPACE_0x8)
+#define SPACE_0x20     TWICE(SPACE_0x10)
+#define SPACE_0x40     TWICE(SPACE_0x20)
+#define SPACE_0x80     TWICE(SPACE_0x40)
+#define SPACE_0x100    TWICE(SPACE_0x80)
+#define SPACE_0x200    TWICE(SPACE_0x100)
+#define SPACE_0x400    TWICE(SPACE_0x200)
+#define SPACE_0x800    TWICE(SPACE_0x400)
+#define SPACE_0x1000   TWICE(SPACE_0x800)
+
+
 /* Various values used in test cases... */
 #define N(val) (val ^ 0xffffffff)
 #define VAL1   0x12345678
index c1b4463dcc839c781004080d7426e78771bad15a..e59bbd496c39174da0a6ee4094fe6f717df97a67 100644 (file)
@@ -32,24 +32,6 @@ static atomic_t waiting_for_crash_ipi;
 
 int machine_kexec_prepare(struct kimage *image)
 {
-       unsigned long page_list;
-       void *reboot_code_buffer;
-       page_list = image->head & PAGE_MASK;
-
-       reboot_code_buffer = page_address(image->control_code_page);
-
-       /* Prepare parameters for reboot_code_buffer*/
-       kexec_start_address = image->start;
-       kexec_indirection_page = page_list;
-       kexec_mach_type = machine_arch_type;
-       kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
-
-       /* copy our kernel relocation code to the control code page */
-       memcpy(reboot_code_buffer,
-              relocate_new_kernel, relocate_new_kernel_size);
-
-       flush_icache_range((unsigned long) reboot_code_buffer,
-                          (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        return 0;
 }
 
@@ -100,14 +82,31 @@ void (*kexec_reinit)(void);
 
 void machine_kexec(struct kimage *image)
 {
+       unsigned long page_list;
        unsigned long reboot_code_buffer_phys;
        void *reboot_code_buffer;
 
+
+       page_list = image->head & PAGE_MASK;
+
        /* we need both effective and real address here */
        reboot_code_buffer_phys =
            page_to_pfn(image->control_code_page) << PAGE_SHIFT;
        reboot_code_buffer = page_address(image->control_code_page);
 
+       /* Prepare parameters for reboot_code_buffer*/
+       kexec_start_address = image->start;
+       kexec_indirection_page = page_list;
+       kexec_mach_type = machine_arch_type;
+       kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
+
+       /* copy our kernel relocation code to the control code page */
+       memcpy(reboot_code_buffer,
+              relocate_new_kernel, relocate_new_kernel_size);
+
+
+       flush_icache_range((unsigned long) reboot_code_buffer,
+                          (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        printk(KERN_INFO "Bye!\n");
 
        if (kexec_reinit)
index 24e2347be6b1043ad7cf87f70ab88fe6e9a270c9..c475379199b1d149adc4f8e33e00f1d544e4b595 100644 (file)
@@ -343,8 +343,14 @@ validate_group(struct perf_event *event)
 {
        struct perf_event *sibling, *leader = event->group_leader;
        struct pmu_hw_events fake_pmu;
+       DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS);
 
-       memset(&fake_pmu, 0, sizeof(fake_pmu));
+       /*
+        * Initialise the fake PMU. We only need to populate the
+        * used_mask for the purposes of validation.
+        */
+       memset(fake_used_mask, 0, sizeof(fake_used_mask));
+       fake_pmu.used_mask = fake_used_mask;
 
        if (!validate_event(&fake_pmu, leader))
                return -ENOSPC;
@@ -396,6 +402,9 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
        int i, err, irq, irqs;
        struct platform_device *pmu_device = armpmu->plat_device;
 
+       if (!pmu_device)
+               return -ENODEV;
+
        err = reserve_pmu(armpmu->type);
        if (err) {
                pr_warning("unable to reserve pmu\n");
index 2c3407ee857675242c874f49adaf9d26339f79bf..2334bf8a650a16a35d5849a4b6c309d5f19eb1f1 100644 (file)
@@ -33,3 +33,4 @@ release_pmu(enum arm_pmu_type type)
 {
        clear_bit_unlock(type, pmu_lock);
 }
+EXPORT_SYMBOL_GPL(release_pmu);
index 75316f0dd02ae3b0be19e10a982f6a5c7e606ff3..3d0c6fb74ae4efe521cfc563ea11e0fa9738d465 100644 (file)
@@ -192,6 +192,9 @@ void cpu_idle(void)
 #endif
 
                        local_irq_disable();
+#ifdef CONFIG_PL310_ERRATA_769419
+                       wmb();
+#endif
                        if (hlt_counter) {
                                local_irq_enable();
                                cpu_relax();
index 7e7977ab994ff92ee4ded30ee728d92ed6c3a520..3448a3f9cc8c90ae71809075f1cc9c2d313fe167 100644 (file)
@@ -461,8 +461,10 @@ static void __init setup_processor(void)
               cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
               proc_arch[cpu_architecture()], cr_alignment);
 
-       sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
-       sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
+       snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
+                list->arch_name, ENDIANNESS);
+       snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c",
+                list->elf_name, ENDIANNESS);
        elf_hwcap = list->elf_hwcap;
 #ifndef CONFIG_ARM_THUMB
        elf_hwcap &= ~HWCAP_THUMB;
index 1040c00405d0f362916c77030249fff754eda5e8..8200deaa14f680b553bdea41652fac0aaa58e23a 100644 (file)
@@ -43,7 +43,7 @@
 
 struct cputopo_arm cpu_topology[NR_CPUS];
 
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
+const struct cpumask *cpu_coregroup_mask(int cpu)
 {
        return &cpu_topology[cpu].core_sibling;
 }
index 10d868a5a48135840278022e153f3610b0b7a640..d6408d1ee543fe5e3ceabbcda01b25efb07676ba 100644 (file)
@@ -1,5 +1,9 @@
+#include <asm/unwind.h>
+
 #if __LINUX_ARM_ARCH__ >= 6
-       .macro  bitop, instr
+       .macro  bitop, name, instr
+ENTRY( \name           )
+UNWIND(        .fnstart        )
        ands    ip, r1, #3
        strneb  r1, [ip]                @ assert word-aligned
        mov     r2, #1
        cmp     r0, #0
        bne     1b
        bx      lr
+UNWIND(        .fnend          )
+ENDPROC(\name          )
        .endm
 
-       .macro  testop, instr, store
+       .macro  testop, name, instr, store
+ENTRY( \name           )
+UNWIND(        .fnstart        )
        ands    ip, r1, #3
        strneb  r1, [ip]                @ assert word-aligned
        mov     r2, #1
        cmp     r0, #0
        movne   r0, #1
 2:     bx      lr
+UNWIND(        .fnend          )
+ENDPROC(\name          )
        .endm
 #else
-       .macro  bitop, instr
+       .macro  bitop, name, instr
+ENTRY( \name           )
+UNWIND(        .fnstart        )
        ands    ip, r1, #3
        strneb  r1, [ip]                @ assert word-aligned
        and     r2, r0, #31
@@ -49,6 +61,8 @@
        str     r2, [r1, r0, lsl #2]
        restore_irqs ip
        mov     pc, lr
+UNWIND(        .fnend          )
+ENDPROC(\name          )
        .endm
 
 /**
@@ -59,7 +73,9 @@
  * Note: we can trivially conditionalise the store instruction
  * to avoid dirtying the data cache.
  */
-       .macro  testop, instr, store
+       .macro  testop, name, instr, store
+ENTRY( \name           )
+UNWIND(        .fnstart        )
        ands    ip, r1, #3
        strneb  r1, [ip]                @ assert word-aligned
        and     r3, r0, #31
@@ -73,5 +89,7 @@
        moveq   r0, #0
        restore_irqs ip
        mov     pc, lr
+UNWIND(        .fnend          )
+ENDPROC(\name          )
        .endm
 #endif
index 68ed5b62e83976d906bad4409fdabda385caaf96..f4027862172f8a4f1082ae06d7568615f3e5ad45 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_change_bit)
-       bitop   eor
-ENDPROC(_change_bit)
+bitop  _change_bit, eor
index 4c04c3b51eeb0d11bc3b755044b0a63ca6f0db1b..f6b75fb64d30557c5b22655adec3ba2bd34b0c07 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_clear_bit)
-       bitop   bic
-ENDPROC(_clear_bit)
+bitop  _clear_bit, bic
index bbee5c66a23e177494875e5db4fc19da97ed0d73..618fedae4b370aac8b65c2a39ae51046b0ff711a 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                .text
 
-ENTRY(_set_bit)
-       bitop   orr
-ENDPROC(_set_bit)
+bitop  _set_bit, orr
index 15a4d431f229440979aaf179fd423eb647b8da0f..4becdc3a59cbb60717bae345ec7b3f58243abdb6 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_change_bit)
-       testop  eor, str
-ENDPROC(_test_and_change_bit)
+testop _test_and_change_bit, eor, str
index 521b66b5b95da197fa661f142547414399a0af59..918841dcce7ad57ef5e880f1c09547404070fbe5 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_clear_bit)
-       testop  bicne, strne
-ENDPROC(_test_and_clear_bit)
+testop _test_and_clear_bit, bicne, strne
index 1c98cc2185bb0885ae0cac805193f52d34345608..8d1b2fe9e4873ba8d53ba75773a7e30e92292b7c 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_set_bit)
-       testop  orreq, streq
-ENDPROC(_test_and_set_bit)
+testop _test_and_set_bit, orreq, streq
index ecdd54dd68c6c0139d10ca50595283bcf94545d7..17632b82dd76a810b11781bf7d5345412ffeebc9 100644 (file)
@@ -137,7 +137,7 @@ static struct clk pwm_clk = {
        .type           = CLK_TYPE_PERIPHERAL,
 };
 static struct clk macb_clk = {
-       .name           = "macb_clk",
+       .name           = "pclk",
        .pmc_mask       = 1 << AT91CAP9_ID_EMAC,
        .type           = CLK_TYPE_PERIPHERAL,
 };
@@ -210,6 +210,8 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
+       /* One additional fake clock for macb_hclk */
+       CLKDEV_CON_ID("hclk", &macb_clk),
        CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
        CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
index a4401d6b5b07b98f46492746f2cfbffc0a00d543..695aecab0a67edf22efc7490bbed9ba6bf67f17b 100644 (file)
@@ -98,7 +98,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 
 static struct resource usba_udc_resources[] = {
        [0] = {
@@ -200,7 +200,7 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
 
 #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
 static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
+static struct macb_platform_data eth_data;
 
 static struct resource eth_resources[] = {
        [0] = {
@@ -227,7 +227,7 @@ static struct platform_device at91cap9_eth_device = {
        .num_resources  = ARRAY_SIZE(eth_resources),
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
+void __init at91_add_device_eth(struct macb_platform_data *data)
 {
        if (!data)
                return;
@@ -264,7 +264,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data)
        platform_device_register(&at91cap9_eth_device);
 }
 #else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
+void __init at91_add_device_eth(struct macb_platform_data *data) {}
 #endif
 
 
@@ -1021,8 +1021,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -1035,7 +1035,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 01d8bbd1468ba5900990cd4cc2f53a37166c3281..5610f14e342eaf76ce4877c8090079677688e924 100644 (file)
@@ -135,7 +135,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
 
 #if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE)
 static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
+static struct macb_platform_data eth_data;
 
 static struct resource eth_resources[] = {
        [0] = {
@@ -162,7 +162,7 @@ static struct platform_device at91rm9200_eth_device = {
        .num_resources  = ARRAY_SIZE(eth_resources),
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
+void __init at91_add_device_eth(struct macb_platform_data *data)
 {
        if (!data)
                return;
@@ -199,7 +199,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data)
        platform_device_register(&at91rm9200_eth_device);
 }
 #else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
+void __init at91_add_device_eth(struct macb_platform_data *data) {}
 #endif
 
 
@@ -877,8 +877,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -891,7 +891,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index b84a9f642f5953a5ff527d3b593b1a628b61232b..249ed1f5912de8347a2b81a95d4da0f70d9d99f5 100644 (file)
@@ -120,7 +120,7 @@ static struct clk ohci_clk = {
        .type           = CLK_TYPE_PERIPHERAL,
 };
 static struct clk macb_clk = {
-       .name           = "macb_clk",
+       .name           = "pclk",
        .pmc_mask       = 1 << AT91SAM9260_ID_EMAC,
        .type           = CLK_TYPE_PERIPHERAL,
 };
@@ -190,6 +190,8 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
+       /* One additional fake clock for macb_hclk */
+       CLKDEV_CON_ID("hclk", &macb_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
index 24b6f8c0440ddc0c4b4661bc1bbf8b4f51c9b399..ff75f7d4091bfe3b85becdd4e6c27f6a911be611 100644 (file)
@@ -136,7 +136,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
 
 #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
 static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
+static struct macb_platform_data eth_data;
 
 static struct resource eth_resources[] = {
        [0] = {
@@ -163,7 +163,7 @@ static struct platform_device at91sam9260_eth_device = {
        .num_resources  = ARRAY_SIZE(eth_resources),
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
+void __init at91_add_device_eth(struct macb_platform_data *data)
 {
        if (!data)
                return;
@@ -200,7 +200,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data)
        platform_device_register(&at91sam9260_eth_device);
 }
 #else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
+void __init at91_add_device_eth(struct macb_platform_data *data) {}
 #endif
 
 
@@ -837,8 +837,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -851,7 +851,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 3b70b3897d950b5abc0f2f56cb68894b9e873b90..ae78f4d03b738851b5e0ef191c26997c34304d9a 100644 (file)
@@ -816,8 +816,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -830,7 +830,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index f83fbb0ee0c58e9bdaab924071bedaf148096bb2..182d112dc59d3a3b83fdf77573d0443f3ecc59c8 100644 (file)
@@ -118,7 +118,7 @@ static struct clk pwm_clk = {
        .type           = CLK_TYPE_PERIPHERAL,
 };
 static struct clk macb_clk = {
-       .name           = "macb_clk",
+       .name           = "pclk",
        .pmc_mask       = 1 << AT91SAM9263_ID_EMAC,
        .type           = CLK_TYPE_PERIPHERAL,
 };
@@ -182,6 +182,8 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
+       /* One additional fake clock for macb_hclk */
+       CLKDEV_CON_ID("hclk", &macb_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
index 3faa1fde9ad9541a95baf25b01f1e9ea9a380c1b..68562ce2af9496fa0364921bc24e809919ac24aa 100644 (file)
@@ -144,7 +144,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
 
 #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
 static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
+static struct macb_platform_data eth_data;
 
 static struct resource eth_resources[] = {
        [0] = {
@@ -171,7 +171,7 @@ static struct platform_device at91sam9263_eth_device = {
        .num_resources  = ARRAY_SIZE(eth_resources),
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
+void __init at91_add_device_eth(struct macb_platform_data *data)
 {
        if (!data)
                return;
@@ -208,7 +208,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data)
        platform_device_register(&at91sam9263_eth_device);
 }
 #else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
+void __init at91_add_device_eth(struct macb_platform_data *data) {}
 #endif
 
 
@@ -1196,8 +1196,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -1210,7 +1210,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 318b0407ea041fa8d8dae59c106d8427ea48b8ec..5a0e522ffa94d41e45c174fc850bf80b89703797 100644 (file)
@@ -150,7 +150,7 @@ static struct clk ac97_clk = {
        .type           = CLK_TYPE_PERIPHERAL,
 };
 static struct clk macb_clk = {
-       .name           = "macb_clk",
+       .name           = "pclk",
        .pmc_mask       = 1 << AT91SAM9G45_ID_EMAC,
        .type           = CLK_TYPE_PERIPHERAL,
 };
@@ -209,6 +209,8 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
+       /* One additional fake clock for macb_hclk */
+       CLKDEV_CON_ID("hclk", &macb_clk),
        /* One additional fake clock for ohci */
        CLKDEV_CON_ID("ohci_clk", &uhphs_clk),
        CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk),
index 000b5e1da9650ede46410c619784b3956bf00a9f..e2cb835c4d7ca4de5aa1b236e4d12166e475f9dc 100644 (file)
@@ -197,7 +197,7 @@ void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {}
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 static struct resource usba_udc_resources[] = {
        [0] = {
                .start  = AT91SAM9G45_UDPHS_FIFO,
@@ -284,7 +284,7 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
 
 #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
 static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
+static struct macb_platform_data eth_data;
 
 static struct resource eth_resources[] = {
        [0] = {
@@ -311,7 +311,7 @@ static struct platform_device at91sam9g45_eth_device = {
        .num_resources  = ARRAY_SIZE(eth_resources),
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
+void __init at91_add_device_eth(struct macb_platform_data *data)
 {
        if (!data)
                return;
@@ -348,7 +348,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data)
        platform_device_register(&at91sam9g45_eth_device);
 }
 #else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
+void __init at91_add_device_eth(struct macb_platform_data *data) {}
 #endif
 
 
@@ -1332,8 +1332,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -1346,7 +1346,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 305a851b5bff950f60b374fc5ab709f51bbebdaf..628eb566d60ce2e5b7620e903417b010aede16fd 100644 (file)
@@ -75,7 +75,7 @@ void __init at91_add_device_hdmac(void) {}
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 
 static struct resource usba_udc_resources[] = {
        [0] = {
@@ -908,8 +908,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -922,7 +922,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 367d5cd5e36288c1c5395aedc6eaec91e2138ccf..a60d98d7c3e24b8947b6d3b949ef8bc6b1a1357d 100644 (file)
@@ -63,7 +63,7 @@ static void __init onearm_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata onearm_eth_data = {
+static struct macb_platform_data __initdata onearm_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
 };
index 0487ea10c2d68bce193eb29c83058e34f3d55550..17fc77925707fcd30ab7c41696158a54e4d85d33 100644 (file)
@@ -103,7 +103,7 @@ static struct spi_board_info afeb9260_spi_devices[] = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata afeb9260_macb_data = {
+static struct macb_platform_data __initdata afeb9260_macb_data = {
        .phy_irq_pin    = AT91_PIN_PA9,
        .is_rmii        = 0,
 };
@@ -130,19 +130,14 @@ static struct mtd_partition __initdata afeb9260_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(afeb9260_nand_partition);
-       return afeb9260_nand_partition;
-}
-
 static struct atmel_nand_data __initdata afeb9260_nand_data = {
        .ale            = 21,
        .cle            = 22,
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
-       .partition_info = nand_partitions,
        .bus_width_16   = 0,
+       .parts          = afeb9260_nand_partition,
+       .num_parts      = ARRAY_SIZE(afeb9260_nand_partition),
 };
 
 
index 747b2eaa9737c134ffcb81006b9b5a807087a3d3..2037d2c40eb4dc501609a3fad59ef7d807c22bf1 100644 (file)
@@ -115,7 +115,7 @@ static struct spi_board_info cam60_spi_devices[] __initdata = {
 /*
  * MACB Ethernet device
  */
-static struct __initdata at91_eth_data cam60_macb_data = {
+static struct __initdata macb_platform_data cam60_macb_data = {
        .phy_irq_pin    = AT91_PIN_PB5,
        .is_rmii        = 0,
 };
@@ -132,19 +132,14 @@ static struct mtd_partition __initdata cam60_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(cam60_nand_partition);
-       return cam60_nand_partition;
-}
-
 static struct atmel_nand_data __initdata cam60_nand_data = {
        .ale            = 21,
        .cle            = 22,
        // .det_pin     = ... not there
        .rdy_pin        = AT91_PIN_PA9,
        .enable_pin     = AT91_PIN_PA7,
-       .partition_info = nand_partitions,
+       .parts          = cam60_nand_partition,
+       .num_parts      = ARRAY_SIZE(cam60_nand_partition),
 };
 
 static struct sam9_smc_config __initdata cam60_nand_smc_config = {
index 062670351a6a11b9f82551378cdb00dc2675de44..af5520c366fe802ce2ce707628b82658cde97bd1 100644 (file)
@@ -153,7 +153,7 @@ static struct at91_mmc_data __initdata cap9adk_mmc_data = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata cap9adk_macb_data = {
+static struct macb_platform_data __initdata cap9adk_macb_data = {
        .is_rmii        = 1,
 };
 
@@ -169,19 +169,14 @@ static struct mtd_partition __initdata cap9adk_nand_partitions[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(cap9adk_nand_partitions);
-       return cap9adk_nand_partitions;
-}
-
 static struct atmel_nand_data __initdata cap9adk_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
 //     .rdy_pin        = ... not connected
        .enable_pin     = AT91_PIN_PD15,
-       .partition_info = nand_partitions,
+       .parts          = cap9adk_nand_partitions,
+       .num_parts      = ARRAY_SIZE(cap9adk_nand_partitions),
 };
 
 static struct sam9_smc_config __initdata cap9adk_nand_smc_config = {
index 774c87fcbd5b8f0ee355bf7b9d7c84822eb95ac9..529b356cdb7d3cfa61a39c2e10944ccd144469b9 100644 (file)
@@ -57,7 +57,7 @@ static void __init carmeva_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata carmeva_eth_data = {
+static struct macb_platform_data __initdata carmeva_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
 };
index fc885a4ce243fbedce8461435cf966c859f68886..04d2b9b5046455b47dbce8f9e19534a2c18eda95 100644 (file)
@@ -99,7 +99,7 @@ static struct at91_udc_data __initdata cpu9krea_udc_data = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata cpu9krea_macb_data = {
+static struct macb_platform_data __initdata cpu9krea_macb_data = {
        .is_rmii        = 1,
 };
 
index d35e65b08ccde481aeac88978fd83d7ca1a329c1..7a4c82e8da51559edfeda6dafeb743a69eaad953 100644 (file)
@@ -82,7 +82,7 @@ static void __init cpuat91_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata cpuat91_eth_data = {
+static struct macb_platform_data __initdata cpuat91_eth_data = {
        .is_rmii        = 1,
 };
 
index c3936665e6457715dedaccb0a8b0be0e0fc5f936..b004b20b8e42d8a6ce2983f972c1e4dbc6bf946d 100644 (file)
@@ -58,7 +58,7 @@ static void __init csb337_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata csb337_eth_data = {
+static struct macb_platform_data __initdata csb337_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC2,
        .is_rmii        = 0,
 };
index 586100e2acbbb5b54c3820b0acd34dafc14f23df..e966de5219c737c53d31f669fc94bd2432e8a6d9 100644 (file)
@@ -52,7 +52,7 @@ static void __init csb637_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata csb637_eth_data = {
+static struct macb_platform_data __initdata csb637_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC0,
        .is_rmii        = 0,
 };
index 45db7a3dbef01b960caa77ff7495a3096a9308bd..3788fa527121c8d7b99c68ea6a6758348e7513af 100644 (file)
@@ -60,7 +60,7 @@ static void __init eb9200_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata eb9200_eth_data = {
+static struct macb_platform_data __initdata eb9200_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
 };
index 2f9c16d29212332f195c85ae7e6e7bc7b3e814c2..af7622eae1a9edf9b6eb79278c1a9409373b3b54 100644 (file)
@@ -64,7 +64,7 @@ static void __init ecb_at91init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata ecb_at91eth_data = {
+static struct macb_platform_data __initdata ecb_at91eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 0,
 };
index 8252c722607b978007efe922f4480052d1902019..8e75867d1d18f65935cbb3e17efd10beb42487b1 100644 (file)
@@ -47,7 +47,7 @@ static void __init eco920_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata eco920_eth_data = {
+static struct macb_platform_data __initdata eco920_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC2,
        .is_rmii        = 1,
 };
index f27d1a780cfa35ef815f6298519d69ea22105019..de8e09642f4e75e417fc35ba6d9c313451ca4efa 100644 (file)
@@ -135,7 +135,7 @@ static struct spi_board_info foxg20_spi_devices[] = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata foxg20_macb_data = {
+static struct macb_platform_data __initdata foxg20_macb_data = {
        .phy_irq_pin    = AT91_PIN_PA7,
        .is_rmii        = 1,
 };
index 2e95949737e69d91e6ca5f23fcfed44ac4325155..51c82f15111909fb6229e6420e8cd716e803e114 100644 (file)
@@ -93,7 +93,7 @@ static struct at91_udc_data __initdata udc_data = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata macb_data = {
+static struct macb_platform_data __initdata macb_data = {
        .phy_irq_pin    = AT91_PIN_PA28,
        .is_rmii        = 1,
 };
index 3bae73e636332fc5ccfef18b6e02c09915728b2d..9628a3defcf45d62a898b59744da29e344f99763 100644 (file)
@@ -61,7 +61,7 @@ static void __init kafa_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata kafa_eth_data = {
+static struct macb_platform_data __initdata kafa_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 0,
 };
index 15a3f1a87ab05f9253dce15afc1bdb4746180665..5ba5244cb6325b9b064dd0265986abc1c984e734 100644 (file)
@@ -69,7 +69,7 @@ static void __init kb9202_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata kb9202_eth_data = {
+static struct macb_platform_data __initdata kb9202_eth_data = {
        .phy_irq_pin    = AT91_PIN_PB29,
        .is_rmii        = 0,
 };
@@ -97,19 +97,14 @@ static struct mtd_partition __initdata kb9202_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(kb9202_nand_partition);
-       return kb9202_nand_partition;
-}
-
 static struct atmel_nand_data __initdata kb9202_nand_data = {
        .ale            = 22,
        .cle            = 21,
        // .det_pin     = ... not there
        .rdy_pin        = AT91_PIN_PC29,
        .enable_pin     = AT91_PIN_PC28,
-       .partition_info = nand_partitions,
+       .parts          = kb9202_nand_partition,
+       .num_parts      = ARRAY_SIZE(kb9202_nand_partition),
 };
 
 static void __init kb9202_board_init(void)
index 6094496f7edb3344843cc32b88ff28acdbefde97..56e7aee11b5915d31c4d44fd1772be6b51f2fca8 100644 (file)
@@ -155,7 +155,7 @@ static struct at91_mmc_data __initdata neocore926_mmc_data = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata neocore926_macb_data = {
+static struct macb_platform_data __initdata neocore926_macb_data = {
        .phy_irq_pin    = AT91_PIN_PE31,
        .is_rmii        = 1,
 };
@@ -182,19 +182,14 @@ static struct mtd_partition __initdata neocore926_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(neocore926_nand_partition);
-       return neocore926_nand_partition;
-}
-
 static struct atmel_nand_data __initdata neocore926_nand_data = {
        .ale                    = 21,
        .cle                    = 22,
        .rdy_pin                = AT91_PIN_PB19,
        .rdy_pin_active_low     = 1,
        .enable_pin             = AT91_PIN_PD15,
-       .partition_info         = nand_partitions,
+       .parts                  = neocore926_nand_partition,
+       .num_parts              = ARRAY_SIZE(neocore926_nand_partition),
 };
 
 static struct sam9_smc_config __initdata neocore926_nand_smc_config = {
index 49e3f699b48e1edff3d73921c178f4426b056896..c545a3e635a4cf1552ec4b5dc0428355b90f098e 100644 (file)
@@ -122,7 +122,7 @@ static struct at91_udc_data __initdata pcontrol_g20_udc_data = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata macb_data = {
+static struct macb_platform_data __initdata macb_data = {
        .phy_irq_pin    = AT91_PIN_PA28,
        .is_rmii        = 1,
 };
index 0a8fe6a1b7c8a8a606241f46d8a0a2ff133a75e7..dc18759a24b49d1fc06336d7eb4c3f0221cd3ce1 100644 (file)
@@ -60,7 +60,7 @@ static void __init picotux200_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata picotux200_eth_data = {
+static struct macb_platform_data __initdata picotux200_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
 };
index 938cc390bea3099c59f67a8988fc3fddfe7c9925..5444d6ac514ab1ae53387aabebcf15b76c19ff54 100644 (file)
@@ -104,7 +104,7 @@ static struct spi_board_info ek_spi_devices[] = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata ek_macb_data = {
+static struct macb_platform_data __initdata ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PA31,
        .is_rmii        = 1,
 };
@@ -130,19 +130,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
index b4ac30e38a9e396102a7a466cd8fb25fc2d05cee..022d0cebda9dfad17696709367552cfebf78ed28 100644 (file)
@@ -65,7 +65,7 @@ static void __init dk_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata dk_eth_data = {
+static struct macb_platform_data __initdata dk_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
 };
@@ -138,19 +138,14 @@ static struct mtd_partition __initdata dk_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(dk_nand_partition);
-       return dk_nand_partition;
-}
-
 static struct atmel_nand_data __initdata dk_nand_data = {
        .ale            = 22,
        .cle            = 21,
        .det_pin        = AT91_PIN_PB1,
        .rdy_pin        = AT91_PIN_PC2,
        // .enable_pin  = ... not there
-       .partition_info = nand_partitions,
+       .parts          = dk_nand_partition,
+       .num_parts      = ARRAY_SIZE(dk_nand_partition),
 };
 
 #define DK_FLASH_BASE  AT91_CHIPSELECT_0
index 99fd7f8aee0e0f378583365575d3be4bd9127bfe..ed275861adef94b58ed57e2b71081bc53e9ce8a2 100644 (file)
@@ -65,7 +65,7 @@ static void __init ek_init_early(void)
        at91_set_serial_console(0);
 }
 
-static struct at91_eth_data __initdata ek_eth_data = {
+static struct macb_platform_data __initdata ek_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
 };
index e927df0175dff55f05ba9ab428a7fe4e5a57138d..ed3b21f7767422ece2773767e4ddcfac11d4aa5b 100644 (file)
@@ -60,7 +60,7 @@ static void __init rsi_ews_init_early(void)
 /*
  * Ethernet
  */
-static struct at91_eth_data rsi_ews_eth_data __initdata = {
+static struct macb_platform_data rsi_ews_eth_data __initdata = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
 };
index 2a21e790250e5bcb9baeb2a0588ce37ed68c526a..3e4b50e6f6ab7e2f83b43a482f05957352c93956 100644 (file)
@@ -109,7 +109,7 @@ static struct spi_board_info ek_spi_devices[] = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata ek_macb_data = {
+static struct macb_platform_data __initdata ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PA7,
        .is_rmii        = 0,
 };
@@ -131,19 +131,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
index 89c8b579bfda2949cc47c43b7bec46e5bb1efbcc..13478e14a543a7408c30fbd50000ccbf13a633e0 100644 (file)
@@ -151,7 +151,7 @@ static struct spi_board_info ek_spi_devices[] = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata ek_macb_data = {
+static struct macb_platform_data __initdata ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PA7,
        .is_rmii        = 1,
 };
@@ -173,19 +173,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
index 3741f43cdae908c9fca1836c48215a812bd07555..b005b738e8ff7bc6dc4af3c8e173421bd9b234c7 100644 (file)
@@ -179,19 +179,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 22,
        .cle            = 21,
 //     .det_pin        = ... not connected
        .rdy_pin        = AT91_PIN_PC15,
        .enable_pin     = AT91_PIN_PC14,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
index a580dd451a41549be5dce7ecfa584da7f2ec5081..fcf194e6e4fed938ea38c4c6b630825295d6384a 100644 (file)
@@ -158,7 +158,7 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata ek_macb_data = {
+static struct macb_platform_data __initdata ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PE31,
        .is_rmii        = 1,
 };
@@ -180,19 +180,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
        .rdy_pin        = AT91_PIN_PA22,
        .enable_pin     = AT91_PIN_PD15,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
index 8d77c2ff96b2bc3351bd3dc0c237e7e8397fa176..78d27cc3cc09f4d0ee9ceb3a87c274baba085e76 100644 (file)
@@ -123,7 +123,7 @@ static struct spi_board_info ek_spi_devices[] = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata ek_macb_data = {
+static struct macb_platform_data __initdata ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PA7,
        .is_rmii        = 1,
 };
@@ -157,19 +157,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 /* det_pin is not connected */
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
index 2d6203ac1a42f87c0bb4b8a3c5774ed7e11e0be1..4e1ee9d87096070e12b23c641dd524a7dac88658 100644 (file)
@@ -115,7 +115,7 @@ static struct mci_platform_data __initdata mci1_data = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata ek_macb_data = {
+static struct macb_platform_data __initdata ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PD5,
        .is_rmii        = 1,
 };
@@ -137,19 +137,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 /* det_pin is not connected */
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
        .rdy_pin        = AT91_PIN_PC8,
        .enable_pin     = AT91_PIN_PC14,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
index 39a28effc3df9d2443211e769c7d7de72508957d..b2b748239f365ab77627a6d96a7c442be91fd161 100644 (file)
@@ -88,19 +88,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        },
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
        .rdy_pin        = AT91_PIN_PD17,
        .enable_pin     = AT91_PIN_PB6,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
index c73d25e5faea84c876b4b7e539aa0f68eb3e2271..fbec934a7ce9c80a7077a257decd89d8f6e418c5 100644 (file)
@@ -65,7 +65,7 @@ static struct at91_udc_data __initdata snapper9260_udc_data = {
        .vbus_polled            = 1,
 };
 
-static struct at91_eth_data snapper9260_macb_data = {
+static struct macb_platform_data snapper9260_macb_data = {
        .is_rmii        = 1,
 };
 
@@ -97,18 +97,12 @@ static struct mtd_partition __initdata snapper9260_nand_partitions[] = {
        },
 };
 
-static struct mtd_partition * __init
-snapper9260_nand_partition_info(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(snapper9260_nand_partitions);
-       return snapper9260_nand_partitions;
-}
-
 static struct atmel_nand_data __initdata snapper9260_nand_data = {
        .ale            = 21,
        .cle            = 22,
        .rdy_pin        = AT91_PIN_PC13,
-       .partition_info = snapper9260_nand_partition_info,
+       .parts          = snapper9260_nand_partitions,
+       .num_parts      = ARRAY_SIZE(snapper9260_nand_partitions),
        .bus_width_16   = 0,
 };
 
index 936e5fd7f40696d6db2680fde276344a7e3950cb..7c06c07d872bab6fb229175286f7c092ca5c11c1 100644 (file)
@@ -157,7 +157,7 @@ static struct at91_udc_data __initdata stamp9g20evb_udc_data = {
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata macb_data = {
+static struct macb_platform_data __initdata macb_data = {
        .phy_irq_pin    = AT91_PIN_PA28,
        .is_rmii        = 1,
 };
index 5852d3d9890c8d53d90ae185fdad8945f0044963..3d84233f78eba13e01a04c2966a78cbcf4dd665f 100644 (file)
@@ -146,7 +146,7 @@ static void __init ek_add_device_spi(void)
 /*
  * MACB Ethernet device
  */
-static struct at91_eth_data __initdata ek_macb_data = {
+static struct macb_platform_data __initdata ek_macb_data = {
        .phy_irq_pin    = AT91_PIN_PE31,
        .is_rmii        = 1,
 };
@@ -190,19 +190,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
        }
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(ek_nand_partition);
-       return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
        .ale            = 21,
        .cle            = 22,
 //     .det_pin        = ... not connected
        .rdy_pin        = AT91_PIN_PA22,
        .enable_pin     = AT91_PIN_PD15,
-       .partition_info = nand_partitions,
+       .parts          = ek_nand_partition,
+       .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata usb_a9260_nand_smc_config = {
index 3c288b396fc4333caca5d1b0710ec9037ffca464..2c40a21b2794c1b19d4e5a112ee5c8838403e9a2 100644 (file)
@@ -110,7 +110,7 @@ static struct gpio_led yl9200_leds[] = {
 /*
  * Ethernet
  */
-static struct at91_eth_data __initdata yl9200_eth_data = {
+static struct macb_platform_data __initdata yl9200_eth_data = {
        .phy_irq_pin            = AT91_PIN_PB28,
        .is_rmii                = 1,
 };
@@ -172,19 +172,14 @@ static struct mtd_partition __initdata yl9200_nand_partition[] = {
        }
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(yl9200_nand_partition);
-       return yl9200_nand_partition;
-}
-
 static struct atmel_nand_data __initdata yl9200_nand_data = {
        .ale            = 6,
        .cle            = 7,
        // .det_pin     = ... not connected
        .rdy_pin        = AT91_PIN_PC14,        /* R/!B (Sheet10) */
        .enable_pin     = AT91_PIN_PC15,        /* !CE  (Sheet10) */
-       .partition_info = nand_partitions,
+       .parts          = yl9200_nand_partition,
+       .num_parts      = ARRAY_SIZE(yl9200_nand_partition),
 };
 
 /*
@@ -389,7 +384,7 @@ static struct spi_board_info yl9200_spi_devices[] = {
 #include <video/s1d13xxxfb.h>
 
 
-static void __init yl9200_init_video(void)
+static void yl9200_init_video(void)
 {
        /* NWAIT Signal */
        at91_set_A_periph(AT91_PIN_PC6, 0);
index f474272c0eacab7af5f77d5745ee8ff5228bb509..a851e6c984218d14533fd5157c7e58fc76c5fc81 100644 (file)
@@ -34,7 +34,8 @@ static struct cpuidle_driver at91_idle_driver = {
 
 /* Actual code that puts the SoC in different idle states */
 static int at91_enter_idle(struct cpuidle_device *dev,
-                              struct cpuidle_state *state)
+                       struct cpuidle_driver *drv,
+                              int index)
 {
        struct timeval before, after;
        int idle_time;
@@ -42,10 +43,10 @@ static int at91_enter_idle(struct cpuidle_device *dev,
 
        local_irq_disable();
        do_gettimeofday(&before);
-       if (state == &dev->states[0])
+       if (index == 0)
                /* Wait for interrupt state */
                cpu_do_idle();
-       else if (state == &dev->states[1]) {
+       else if (index == 1) {
                asm("b 1f; .align 5; 1:");
                asm("mcr p15, 0, r0, c7, c10, 4");      /* drain write buffer */
                saved_lpr = sdram_selfrefresh_enable();
@@ -56,34 +57,38 @@ static int at91_enter_idle(struct cpuidle_device *dev,
        local_irq_enable();
        idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
                        (after.tv_usec - before.tv_usec);
-       return idle_time;
+
+       dev->last_residency = idle_time;
+       return index;
 }
 
 /* Initialize CPU idle by registering the idle states */
 static int at91_init_cpuidle(void)
 {
        struct cpuidle_device *device;
-
-       cpuidle_register_driver(&at91_idle_driver);
+       struct cpuidle_driver *driver = &at91_idle_driver;
 
        device = &per_cpu(at91_cpuidle_device, smp_processor_id());
        device->state_count = AT91_MAX_STATES;
+       driver->state_count = AT91_MAX_STATES;
 
        /* Wait for interrupt state */
-       device->states[0].enter = at91_enter_idle;
-       device->states[0].exit_latency = 1;
-       device->states[0].target_residency = 10000;
-       device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-       strcpy(device->states[0].name, "WFI");
-       strcpy(device->states[0].desc, "Wait for interrupt");
+       driver->states[0].enter = at91_enter_idle;
+       driver->states[0].exit_latency = 1;
+       driver->states[0].target_residency = 10000;
+       driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+       strcpy(driver->states[0].name, "WFI");
+       strcpy(driver->states[0].desc, "Wait for interrupt");
 
        /* Wait for interrupt and RAM self refresh state */
-       device->states[1].enter = at91_enter_idle;
-       device->states[1].exit_latency = 10;
-       device->states[1].target_residency = 10000;
-       device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-       strcpy(device->states[1].name, "RAM_SR");
-       strcpy(device->states[1].desc, "WFI and RAM Self Refresh");
+       driver->states[1].enter = at91_enter_idle;
+       driver->states[1].exit_latency = 10;
+       driver->states[1].target_residency = 10000;
+       driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+       strcpy(driver->states[1].name, "RAM_SR");
+       strcpy(driver->states[1].desc, "WFI and RAM Self Refresh");
+
+       cpuidle_register_driver(&at91_idle_driver);
 
        if (cpuidle_register_device(device)) {
                printk(KERN_ERR "at91_init_cpuidle: Failed registering\n");
index d07767f4052edf316e74598b8fcc04f121fe7372..e209a2992245683d4812c99b8c2250a589e1deb5 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/atmel-mci.h>
 #include <sound/atmel-ac97c.h>
 #include <linux/serial.h>
+#include <linux/platform_data/macb.h>
 
  /* USB Device */
 struct at91_udc_data {
@@ -81,18 +82,7 @@ extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
   /* atmel-mci platform config */
 extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data);
 
- /* Ethernet (EMAC & MACB) */
-struct at91_eth_data {
-       u32             phy_mask;
-       u8              phy_irq_pin;    /* PHY IRQ */
-       u8              is_rmii;        /* using RMII interface? */
-};
-extern void __init at91_add_device_eth(struct at91_eth_data *data);
-
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91SAM9G20) || defined(CONFIG_ARCH_AT91CAP9) \
-       || defined(CONFIG_ARCH_AT91SAM9G45)
-#define eth_platform_data      at91_eth_data
-#endif
+extern void __init at91_add_device_eth(struct macb_platform_data *data);
 
  /* USB Host */
 struct at91_usbh_data {
@@ -117,7 +107,8 @@ struct atmel_nand_data {
        u8              ale;            /* address line number connected to ALE */
        u8              cle;            /* address line number connected to CLE */
        u8              bus_width_16;   /* buswidth is 16 bit */
-       struct mtd_partition* (*partition_info)(int, int*);
+       struct mtd_partition *parts;
+       unsigned int    num_parts;
 };
 extern void __init at91_add_device_nand(struct atmel_nand_data *data);
 
index 8eb459f3f5b7a4c43769c2283bba785ce17131be..8e4a1bd0ab1d6ebd2eaefd443d3b354c99cda8d5 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
+#include <mach/hardware.h>
+
 #define VMALLOC_END            (AT91_VIRT_BASE & PGDIR_MASK)
 
 #endif
index 43eadbcc29ede940fd5c4035c2b6abacbcdb2a3b..430da120a297fe08620eaba672c65e283171bd99 100644 (file)
@@ -235,7 +235,7 @@ void __init bcmring_init_timer(void)
         */
        bcmring_clocksource_init();
 
-       sp804_clockevents_register(TIMER0_VA_BASE, IRQ_TIMER0, "timer0");
+       sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMER0, "timer0");
 }
 
 struct sys_timer bcmring_timer = {
index b52b8de91bde72c2a4847c1a37a44f425974612d..f4d4d6d174d06e9c049756de6089e02e790abe8a 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/mm.h>
 #include <linux/pfn.h>
 #include <linux/atomic.h>
+#include <linux/sched.h>
 #include <mach/dma.h>
 
 /* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
index 26d94c0b555cb210d53ebde3df94348e524cc210..11c3db985285880ac7a2f22b13b51ff677fcae46 100644 (file)
@@ -377,7 +377,7 @@ static struct davinci_nand_pdata da830_evm_nand_pdata = {
        .nr_parts       = ARRAY_SIZE(da830_evm_nand_partitions),
        .ecc_mode       = NAND_ECC_HW,
        .ecc_bits       = 4,
-       .options        = NAND_USE_FLASH_BBT,
+       .bbt_options    = NAND_BBT_USE_FLASH,
        .bbt_td         = &da830_evm_nand_bbt_main_descr,
        .bbt_md         = &da830_evm_nand_bbt_mirror_descr,
        .timing         = &da830_evm_nandflash_timing,
index ec21663f8ddc073516f65a7b5fe7e99b14073de4..1d7d2499522674f94143771e84aa26f323869ac7 100644 (file)
@@ -256,7 +256,7 @@ static struct davinci_nand_pdata da850_evm_nandflash_data = {
        .nr_parts       = ARRAY_SIZE(da850_evm_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
        .ecc_bits       = 4,
-       .options        = NAND_USE_FLASH_BBT,
+       .bbt_options    = NAND_BBT_USE_FLASH,
        .timing         = &da850_evm_nandflash_timing,
 };
 
index 65566280b7c987f54243df5559f1c458807e020d..4e0e707c313d7b9e51f87acbece9b3e0af3a97f3 100644 (file)
@@ -77,7 +77,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW,
-       .options                = NAND_USE_FLASH_BBT,
+       .bbt_options            = NAND_BBT_USE_FLASH,
        .ecc_bits               = 4,
 };
 
index b307470b071dfd0679ae4f3d2a11d84e0d001810..ff2d2413279a26482411dcbb8728266b93e8bbe4 100644 (file)
@@ -74,7 +74,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW_SYNDROME,
-       .options                = NAND_USE_FLASH_BBT,
+       .bbt_options            = NAND_BBT_USE_FLASH,
 };
 
 static struct resource davinci_nand_resources[] = {
index 04c43abcca66f48781e9de61cdd2b1374082beb5..1918ae711428b3d5b9cf2556c212bfc156f90664 100644 (file)
@@ -139,7 +139,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW,
-       .options                = NAND_USE_FLASH_BBT,
+       .bbt_options            = NAND_BBT_USE_FLASH,
        .ecc_bits               = 4,
 };
 
index 28fafa7819bcdd727834b9165ec7e440267e6c33..0cf8abf78d33d878acd1dbf3480e7d92403e2c66 100644 (file)
@@ -151,7 +151,7 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = {
        .parts          = davinci_evm_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_evm_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
-       .options        = NAND_USE_FLASH_BBT,
+       .bbt_options    = NAND_BBT_USE_FLASH,
        .timing         = &davinci_evm_nandflash_timing,
 };
 
index 6efc84cceca093eff0299da9ddfae3b666c1eadd..3cfff555e8f22a842eb75f3614d5e5605eaf642b 100644 (file)
@@ -396,7 +396,8 @@ static struct davinci_nand_pdata mityomapl138_nandflash_data = {
        .parts          = mityomapl138_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(mityomapl138_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
-       .options        = NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16,
+       .bbt_options    = NAND_BBT_USE_FLASH,
+       .options        = NAND_BUSWIDTH_16,
        .ecc_bits       = 1, /* 4 bit mode is not supported with 16 bit NAND */
 };
 
index 38d6f644d8b9e39ae32aaeaba4d08d0f00d47915..e5f231aefee428bfd26cde4b4b05d7de45627992 100644 (file)
@@ -87,7 +87,7 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
        .parts          = davinci_ntosd2_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
-       .options        = NAND_USE_FLASH_BBT,
+       .bbt_options    = NAND_BBT_USE_FLASH,
 };
 
 static struct resource davinci_ntosd2_nandflash_resource[] = {
index 90ee7b5aabdcfabdf1ccaf30ea1129a1377a6a02..f69e40a29e0256005801d46756529dadb3e1d5db 100644 (file)
@@ -144,7 +144,7 @@ static struct davinci_nand_pdata nand_config = {
        .parts          = nand_partitions,
        .nr_parts       = ARRAY_SIZE(nand_partitions),
        .ecc_mode       = NAND_ECC_HW,
-       .options        = NAND_USE_FLASH_BBT,
+       .bbt_options    = NAND_BBT_USE_FLASH,
        .ecc_bits       = 1,
 };
 
index 60d2f4871afa51c5670e20319d08e26f0213eeff..a30c7c5a6d83a4703b968fe15212faec24ee6db1 100644 (file)
@@ -79,9 +79,11 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {
 
 /* Actual code that puts the SoC in different idle states */
 static int davinci_enter_idle(struct cpuidle_device *dev,
-                                               struct cpuidle_state *state)
+                               struct cpuidle_driver *drv,
+                                               int index)
 {
-       struct davinci_ops *ops = cpuidle_get_statedata(state);
+       struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+       struct davinci_ops *ops = cpuidle_get_statedata(state_usage);
        struct timeval before, after;
        int idle_time;
 
@@ -99,13 +101,17 @@ static int davinci_enter_idle(struct cpuidle_device *dev,
        local_irq_enable();
        idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
                        (after.tv_usec - before.tv_usec);
-       return idle_time;
+
+       dev->last_residency = idle_time;
+
+       return index;
 }
 
 static int __init davinci_cpuidle_probe(struct platform_device *pdev)
 {
        int ret;
        struct cpuidle_device *device;
+       struct cpuidle_driver *driver = &davinci_idle_driver;
        struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
 
        device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
@@ -117,32 +123,33 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
 
        ddr2_reg_base = pdata->ddr2_ctlr_base;
 
-       ret = cpuidle_register_driver(&davinci_idle_driver);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register driver\n");
-               return ret;
-       }
-
        /* Wait for interrupt state */
-       device->states[0].enter = davinci_enter_idle;
-       device->states[0].exit_latency = 1;
-       device->states[0].target_residency = 10000;
-       device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-       strcpy(device->states[0].name, "WFI");
-       strcpy(device->states[0].desc, "Wait for interrupt");
+       driver->states[0].enter = davinci_enter_idle;
+       driver->states[0].exit_latency = 1;
+       driver->states[0].target_residency = 10000;
+       driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+       strcpy(driver->states[0].name, "WFI");
+       strcpy(driver->states[0].desc, "Wait for interrupt");
 
        /* Wait for interrupt and DDR self refresh state */
-       device->states[1].enter = davinci_enter_idle;
-       device->states[1].exit_latency = 10;
-       device->states[1].target_residency = 10000;
-       device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-       strcpy(device->states[1].name, "DDR SR");
-       strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+       driver->states[1].enter = davinci_enter_idle;
+       driver->states[1].exit_latency = 10;
+       driver->states[1].target_residency = 10000;
+       driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+       strcpy(driver->states[1].name, "DDR SR");
+       strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
        if (pdata->ddr2_pdown)
                davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
-       cpuidle_set_statedata(&device->states[1], &davinci_states[1]);
+       cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);
 
        device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
+       driver->state_count = DAVINCI_CPUIDLE_MAX_STATES;
+
+       ret = cpuidle_register_driver(&davinci_idle_driver);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register driver\n");
+               return ret;
+       }
 
        ret = cpuidle_register_device(device);
        if (ret) {
index 025151049f0517a103c4efb96ee86d465c3fff19..1cf555aef896c39342bd7306c09cfa1358451fe6 100644 (file)
@@ -74,8 +74,10 @@ struct davinci_nand_pdata {          /* platform_data */
        nand_ecc_modes_t        ecc_mode;
        u8                      ecc_bits;
 
-       /* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
+       /* e.g. NAND_BUSWIDTH_16 */
        unsigned                options;
+       /* e.g. NAND_BBT_USE_FLASH */
+       unsigned                bbt_options;
 
        /* Main and mirror bbt descriptor overrides */
        struct nand_bbt_descr   *bbt_td;
index 1ade3c34050741411701d185e224d76cb253a36f..8b2f1435bcacfa2a60ac6a53e75f369ee55a11d8 100644 (file)
@@ -116,8 +116,9 @@ static struct mtd_partition ts72xx_nand_parts[] = {
                .mask_flags     = MTD_WRITEABLE,        /* force read-only */
        }, {
                .name           = "Linux",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = 0,                    /* filled in later */
+               .offset         = MTDPART_OFS_RETAIN,
+               .size           = TS72XX_REDBOOT_PART_SIZE,
+                               /* leave so much for last partition */
        }, {
                .name           = "RedBoot",
                .offset         = MTDPART_OFS_APPEND,
@@ -126,28 +127,14 @@ static struct mtd_partition ts72xx_nand_parts[] = {
        },
 };
 
-static void ts72xx_nand_set_parts(uint64_t size,
-                                 struct platform_nand_chip *chip)
-{
-       /* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */
-       if (size == SZ_32M || size == SZ_128M) {
-               /* Set the "Linux" partition size */
-               ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE;
-
-               chip->partitions = ts72xx_nand_parts;
-               chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts);
-       } else {
-               pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20);
-       }
-}
-
 static struct platform_nand_data ts72xx_nand_data = {
        .chip = {
                .nr_chips       = 1,
                .chip_offset    = 0,
                .chip_delay     = 15,
                .part_probe_types = ts72xx_nand_part_probes,
-               .set_parts      = ts72xx_nand_set_parts,
+               .partitions     = ts72xx_nand_parts,
+               .nr_partitions  = ARRAY_SIZE(ts72xx_nand_parts),
        },
        .ctrl = {
                .cmd_ctrl       = ts72xx_nand_hwcontrol,
index bf7e96f2793a009fe4c96706d6022c1a63a0199d..4ebb382c597918e1053a221b35bd52a9e9d1b39a 100644 (file)
 #include <linux/init.h>
 #include <linux/cpuidle.h>
 #include <linux/io.h>
+#include <linux/export.h>
+#include <linux/time.h>
 
 #include <asm/proc-fns.h>
 
 static int exynos4_enter_idle(struct cpuidle_device *dev,
-                             struct cpuidle_state *state);
+                       struct cpuidle_driver *drv,
+                             int index);
 
 static struct cpuidle_state exynos4_cpuidle_set[] = {
        [0] = {
@@ -37,7 +40,8 @@ static struct cpuidle_driver exynos4_idle_driver = {
 };
 
 static int exynos4_enter_idle(struct cpuidle_device *dev,
-                             struct cpuidle_state *state)
+                               struct cpuidle_driver *drv,
+                             int index)
 {
        struct timeval before, after;
        int idle_time;
@@ -52,29 +56,31 @@ static int exynos4_enter_idle(struct cpuidle_device *dev,
        idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
                    (after.tv_usec - before.tv_usec);
 
-       return idle_time;
+       dev->last_residency = idle_time;
+       return index;
 }
 
 static int __init exynos4_init_cpuidle(void)
 {
        int i, max_cpuidle_state, cpu_id;
        struct cpuidle_device *device;
-
+       struct cpuidle_driver *drv = &exynos4_idle_driver;
+
+       /* Setup cpuidle driver */
+       drv->state_count = (sizeof(exynos4_cpuidle_set) /
+                                      sizeof(struct cpuidle_state));
+       max_cpuidle_state = drv->state_count;
+       for (i = 0; i < max_cpuidle_state; i++) {
+               memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
+                               sizeof(struct cpuidle_state));
+       }
        cpuidle_register_driver(&exynos4_idle_driver);
 
        for_each_cpu(cpu_id, cpu_online_mask) {
                device = &per_cpu(exynos4_cpuidle_device, cpu_id);
                device->cpu = cpu_id;
 
-               device->state_count = (sizeof(exynos4_cpuidle_set) /
-                                              sizeof(struct cpuidle_state));
-
-               max_cpuidle_state = device->state_count;
-
-               for (i = 0; i < max_cpuidle_state; i++) {
-                       memcpy(&device->states[i], &exynos4_cpuidle_set[i],
-                                       sizeof(struct cpuidle_state));
-               }
+               device->state_count = drv->state_count;
 
                if (cpuidle_register_device(device)) {
                        printk(KERN_ERR "CPUidle register device failed\n,");
index b82dcf08e747e1052ea13b4a11feef25b7f7775b..88660d500f5be259bde8bd94389805881cf8975e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
+#include <linux/smp.h>
 
 #include <asm/cacheflush.h>
 #include <asm/unified.h>
@@ -72,6 +73,9 @@ static void __init highbank_map_io(void)
 
 void highbank_set_cpu_jump(int cpu, void *jump_addr)
 {
+#ifdef CONFIG_SMP
+       cpu = cpu_logical_map(cpu);
+#endif
        writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu));
        __cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
        outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
index 5f7f9c2a34aec39cdd4f312c326cd0005d5ea027..c44aa974e79c473d123631236269bdb8c2daa8a3 100644 (file)
@@ -10,11 +10,6 @@ config HAVE_IMX_MMDC
 config HAVE_IMX_SRC
        bool
 
-#
-# ARCH_MX31 and ARCH_MX35 are left for compatibility
-# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2.
-# To easily distinguish good and reviewed from unreviewed usages new (and IMHO
-# more sensible) names are used: SOC_IMX31 and SOC_IMX35
 config ARCH_MX1
        bool
 
@@ -27,12 +22,6 @@ config ARCH_MX25
 config MACH_MX27
        bool
 
-config ARCH_MX31
-       bool
-
-config ARCH_MX35
-       bool
-
 config SOC_IMX1
        bool
        select ARCH_MX1
@@ -72,7 +61,6 @@ config SOC_IMX31
        select CPU_V6
        select IMX_HAVE_PLATFORM_MXC_RNGA
        select ARCH_MXC_AUDMUX_V2
-       select ARCH_MX31
        select MXC_AVIC
        select SMP_ON_UP if SMP
 
@@ -82,7 +70,6 @@ config SOC_IMX35
        select ARCH_MXC_IOMUX_V3
        select ARCH_MXC_AUDMUX_V2
        select HAVE_EPIT
-       select ARCH_MX35
        select MXC_AVIC
        select SMP_ON_UP if SMP
 
index 22d85889f622917ece0fe5310751bf4ab488fed3..cfede5768aa0f788a6d8f6fd8893578a5c4ed75b 100644 (file)
@@ -1,22 +1,26 @@
-zreladdr-$(CONFIG_ARCH_MX1)    += 0x08008000
-params_phys-$(CONFIG_ARCH_MX1) := 0x08000100
-initrd_phys-$(CONFIG_ARCH_MX1) := 0x08800000
+zreladdr-$(CONFIG_SOC_IMX1)    += 0x08008000
+params_phys-$(CONFIG_SOC_IMX1) := 0x08000100
+initrd_phys-$(CONFIG_SOC_IMX1) := 0x08800000
 
-zreladdr-$(CONFIG_MACH_MX21)   += 0xC0008000
-params_phys-$(CONFIG_MACH_MX21)        := 0xC0000100
-initrd_phys-$(CONFIG_MACH_MX21)        := 0xC0800000
+zreladdr-$(CONFIG_SOC_IMX21)   += 0xC0008000
+params_phys-$(CONFIG_SOC_IMX21)        := 0xC0000100
+initrd_phys-$(CONFIG_SOC_IMX21)        := 0xC0800000
 
-zreladdr-$(CONFIG_ARCH_MX25)   += 0x80008000
-params_phys-$(CONFIG_ARCH_MX25)        := 0x80000100
-initrd_phys-$(CONFIG_ARCH_MX25)        := 0x80800000
+zreladdr-$(CONFIG_SOC_IMX25)   += 0x80008000
+params_phys-$(CONFIG_SOC_IMX25)        := 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX25)        := 0x80800000
 
-zreladdr-$(CONFIG_MACH_MX27)   += 0xA0008000
-params_phys-$(CONFIG_MACH_MX27)        := 0xA0000100
-initrd_phys-$(CONFIG_MACH_MX27)        := 0xA0800000
+zreladdr-$(CONFIG_SOC_IMX27)   += 0xA0008000
+params_phys-$(CONFIG_SOC_IMX27)        := 0xA0000100
+initrd_phys-$(CONFIG_SOC_IMX27)        := 0xA0800000
 
-zreladdr-$(CONFIG_ARCH_MX3)    += 0x80008000
-params_phys-$(CONFIG_ARCH_MX3) := 0x80000100
-initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000
+zreladdr-$(CONFIG_SOC_IMX31)   += 0x80008000
+params_phys-$(CONFIG_SOC_IMX31)        := 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX31)        := 0x80800000
+
+zreladdr-$(CONFIG_SOC_IMX35)   += 0x80008000
+params_phys-$(CONFIG_SOC_IMX35)        := 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX35)        := 0x80800000
 
 zreladdr-$(CONFIG_SOC_IMX6Q)   += 0x10008000
 params_phys-$(CONFIG_SOC_IMX6Q)        := 0x10000100
index e0b926dfecedbf2874b03ec726acaf591cd2e94a..039a7abb165a35f4afc10ae08dbb7cc62f1121f7 100644 (file)
@@ -1139,7 +1139,7 @@ static int _clk_set_rate(struct clk *clk, unsigned long rate)
                return -EINVAL;
 
        max_div = ((d->bm_pred >> d->bp_pred) + 1) *
-                 ((d->bm_pred >> d->bp_pred) + 1);
+                 ((d->bm_podf >> d->bp_podf) + 1);
 
        div = parent_rate / rate;
        if (div == 0)
@@ -1953,14 +1953,17 @@ static struct map_desc imx6q_clock_desc[] = {
        imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
 };
 
+void __init imx6q_clock_map_io(void)
+{
+       iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
+}
+
 int __init mx6q_clocks_init(void)
 {
        struct device_node *np;
        void __iomem *base;
        int i, irq;
 
-       iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
-
        /* retrieve the freqency of fixed clocks from device tree */
        for_each_compatible_node(np, NULL, "fixed-clock") {
                u32 rate;
@@ -2002,6 +2005,21 @@ int __init mx6q_clocks_init(void)
        clk_set_rate(&asrc_serial_clk, 1500000);
        clk_set_rate(&enfc_clk, 11000000);
 
+       /*
+        * Before pinctrl API is available, we have to rely on the pad
+        * configuration set up by bootloader.  For usdhc example here,
+        * u-boot sets up the pads for 49.5 MHz case, and we have to lower
+        * the usdhc clock from 198 to 49.5 MHz to match the pad configuration.
+        *
+        * FIXME: This is should be removed after pinctrl API is available.
+        * At that time, usdhc driver can call pinctrl API to change pad
+        * configuration dynamically per different usdhc clock settings.
+        */
+       clk_set_rate(&usdhc1_clk, 49500000);
+       clk_set_rate(&usdhc2_clk, 49500000);
+       clk_set_rate(&usdhc3_clk, 49500000);
+       clk_set_rate(&usdhc4_clk, 49500000);
+
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
        base = of_iomap(np, 0);
        WARN_ON(!base);
index 8bf5fa349484e2da42a4c6deea64bc042b1263e3..9cd860a27af5f797cff2b9e5ceaf1798e09e8777 100644 (file)
@@ -34,6 +34,7 @@ static void __init imx6q_map_io(void)
 {
        imx_lluart_map_io();
        imx_scu_map_io();
+       imx6q_clock_map_io();
 }
 
 static void __init imx6q_gpio_add_irq_domain(struct device_node *np,
index 9f0e82ec3398dfcf7e83c8df246e54cdf53b9503..31807d2a8b7bf1a65d57c8f4cb748bb9e6697934 100644 (file)
 static void imx3_idle(void)
 {
        unsigned long reg = 0;
-       __asm__ __volatile__(
-               /* disable I and D cache */
-               "mrc p15, 0, %0, c1, c0, 0\n"
-               "bic %0, %0, #0x00001000\n"
-               "bic %0, %0, #0x00000004\n"
-               "mcr p15, 0, %0, c1, c0, 0\n"
-               /* invalidate I cache */
-               "mov %0, #0\n"
-               "mcr p15, 0, %0, c7, c5, 0\n"
-               /* clear and invalidate D cache */
-               "mov %0, #0\n"
-               "mcr p15, 0, %0, c7, c14, 0\n"
-               /* WFI */
-               "mov %0, #0\n"
-               "mcr p15, 0, %0, c7, c0, 4\n"
-               "nop\n" "nop\n" "nop\n" "nop\n"
-               "nop\n" "nop\n" "nop\n"
-               /* enable I and D cache */
-               "mrc p15, 0, %0, c1, c0, 0\n"
-               "orr %0, %0, #0x00001000\n"
-               "orr %0, %0, #0x00000004\n"
-               "mcr p15, 0, %0, c1, c0, 0\n"
-               : "=r" (reg));
+
+       if (!need_resched())
+               __asm__ __volatile__(
+                       /* disable I and D cache */
+                       "mrc p15, 0, %0, c1, c0, 0\n"
+                       "bic %0, %0, #0x00001000\n"
+                       "bic %0, %0, #0x00000004\n"
+                       "mcr p15, 0, %0, c1, c0, 0\n"
+                       /* invalidate I cache */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c5, 0\n"
+                       /* clear and invalidate D cache */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c14, 0\n"
+                       /* WFI */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c0, 4\n"
+                       "nop\n" "nop\n" "nop\n" "nop\n"
+                       "nop\n" "nop\n" "nop\n"
+                       /* enable I and D cache */
+                       "mrc p15, 0, %0, c1, c0, 0\n"
+                       "orr %0, %0, #0x00001000\n"
+                       "orr %0, %0, #0x00000004\n"
+                       "mcr p15, 0, %0, c1, c0, 0\n"
+                       : "=r" (reg));
+       local_irq_enable();
 }
 
 static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
@@ -108,6 +111,7 @@ void imx3_init_l2x0(void)
        l2x0_init(l2x0_base, 0x00030024, 0x00000000);
 }
 
+#ifdef CONFIG_SOC_IMX31
 static struct map_desc mx31_io_desc[] __initdata = {
        imx_map_entry(MX31, X_MEMC, MT_DEVICE),
        imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
@@ -126,33 +130,11 @@ void __init mx31_map_io(void)
        iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
 }
 
-static struct map_desc mx35_io_desc[] __initdata = {
-       imx_map_entry(MX35, X_MEMC, MT_DEVICE),
-       imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
-       imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
-       imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
-       imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-void __init mx35_map_io(void)
-{
-       iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
-}
-
 void __init imx31_init_early(void)
 {
        mxc_set_cpu_type(MXC_CPU_MX31);
        mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
-       imx_idle = imx3_idle;
-       imx_ioremap = imx3_ioremap;
-}
-
-void __init imx35_init_early(void)
-{
-       mxc_set_cpu_type(MXC_CPU_MX35);
-       mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
-       mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
-       imx_idle = imx3_idle;
+       pm_idle = imx3_idle;
        imx_ioremap = imx3_ioremap;
 }
 
@@ -161,11 +143,6 @@ void __init mx31_init_irq(void)
        mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
 }
 
-void __init mx35_init_irq(void)
-{
-       mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-}
-
 static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
        .per_2_per_addr = 1677,
 };
@@ -199,6 +176,35 @@ void __init imx31_soc_init(void)
 
        imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
 }
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+static struct map_desc mx35_io_desc[] __initdata = {
+       imx_map_entry(MX35, X_MEMC, MT_DEVICE),
+       imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
+       imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
+       imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
+       imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+void __init mx35_map_io(void)
+{
+       iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
+}
+
+void __init imx35_init_early(void)
+{
+       mxc_set_cpu_type(MXC_CPU_MX35);
+       mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
+       mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
+       pm_idle = imx3_idle;
+       imx_ioremap = imx3_ioremap;
+}
+
+void __init mx35_init_irq(void)
+{
+       mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
+}
 
 static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
        .ap_2_ap_addr = 642,
@@ -254,3 +260,4 @@ void __init imx35_soc_init(void)
 
        imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
 }
+#endif /* ifdef CONFIG_SOC_IMX35 */
index 36cacbd0dcc2fa8c5d98bd5cb1e141a9d30e3503..a8e33681b73251f498a7cfee463f20c3f6d0e1ff 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/smp.h>
 #include <asm/unified.h>
 
 #define SRC_SCR                                0x000
 
 static void __iomem *src_base;
 
+#ifndef CONFIG_SMP
+#define cpu_logical_map(cpu)           0
+#endif
+
 void imx_enable_cpu(int cpu, bool enable)
 {
        u32 mask, val;
 
+       cpu = cpu_logical_map(cpu);
        mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
        val = readl_relaxed(src_base + SRC_SCR);
        val = enable ? val | mask : val & ~mask;
@@ -35,6 +41,7 @@ void imx_enable_cpu(int cpu, bool enable)
 
 void imx_set_cpu_jump(int cpu, void *jump_addr)
 {
+       cpu = cpu_logical_map(cpu);
        writel_relaxed(BSYM(virt_to_phys(jump_addr)),
                       src_base + SRC_GPR1 + cpu * 8);
 }
index 864e569f684ea5ad79545713dc9d2be995a29699..7088180b018b6087546b2c5761f9618baca27c6a 100644 (file)
@@ -33,17 +33,18 @@ static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
 
 /* Actual code that puts the SoC in different idle states */
 static int kirkwood_enter_idle(struct cpuidle_device *dev,
-                              struct cpuidle_state *state)
+                               struct cpuidle_driver *drv,
+                              int index)
 {
        struct timeval before, after;
        int idle_time;
 
        local_irq_disable();
        do_gettimeofday(&before);
-       if (state == &dev->states[0])
+       if (index == 0)
                /* Wait for interrupt state */
                cpu_do_idle();
-       else if (state == &dev->states[1]) {
+       else if (index == 1) {
                /*
                 * Following write will put DDR in self refresh.
                 * Note that we have 256 cycles before DDR puts it
@@ -58,35 +59,40 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev,
        local_irq_enable();
        idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
                        (after.tv_usec - before.tv_usec);
-       return idle_time;
+
+       /* Update last residency */
+       dev->last_residency = idle_time;
+
+       return index;
 }
 
 /* Initialize CPU idle by registering the idle states */
 static int kirkwood_init_cpuidle(void)
 {
        struct cpuidle_device *device;
-
-       cpuidle_register_driver(&kirkwood_idle_driver);
+       struct cpuidle_driver *driver = &kirkwood_idle_driver;
 
        device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
        device->state_count = KIRKWOOD_MAX_STATES;
+       driver->state_count = KIRKWOOD_MAX_STATES;
 
        /* Wait for interrupt state */
-       device->states[0].enter = kirkwood_enter_idle;
-       device->states[0].exit_latency = 1;
-       device->states[0].target_residency = 10000;
-       device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-       strcpy(device->states[0].name, "WFI");
-       strcpy(device->states[0].desc, "Wait for interrupt");
+       driver->states[0].enter = kirkwood_enter_idle;
+       driver->states[0].exit_latency = 1;
+       driver->states[0].target_residency = 10000;
+       driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+       strcpy(driver->states[0].name, "WFI");
+       strcpy(driver->states[0].desc, "Wait for interrupt");
 
        /* Wait for interrupt and DDR self refresh state */
-       device->states[1].enter = kirkwood_enter_idle;
-       device->states[1].exit_latency = 10;
-       device->states[1].target_residency = 10000;
-       device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-       strcpy(device->states[1].name, "DDR SR");
-       strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+       driver->states[1].enter = kirkwood_enter_idle;
+       driver->states[1].exit_latency = 10;
+       driver->states[1].target_residency = 10000;
+       driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+       strcpy(driver->states[1].name, "DDR SR");
+       strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
 
+       cpuidle_register_driver(&kirkwood_idle_driver);
        if (cpuidle_register_device(device)) {
                printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
                return -EIO;
index edcbadad31c1219d97cf57d7b237609e72bd03b4..f0d236dfb02b97d08c46eaa54c70b0ec594cae08 100644 (file)
@@ -167,8 +167,9 @@ static struct mtd_partition aspenite_nand_partitions[] = {
 
 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
        .enable_arbiter = 1,
-       .parts          = aspenite_nand_partitions,
-       .nr_parts       = ARRAY_SIZE(aspenite_nand_partitions),
+       .num_cs = 1,
+       .parts[0]       = aspenite_nand_partitions,
+       .nr_parts[0]    = ARRAY_SIZE(aspenite_nand_partitions),
 };
 
 static struct i2c_board_info aspenite_i2c_info[] __initdata = {
index 933420a7c3ba4fffa516e774a04a222ec2692cd0..e266f66a4670a55d566b41016b35a7d088bb9a65 100644 (file)
@@ -182,7 +182,7 @@ static void __init gplugd_init(void)
 
        /* on-chip devices */
        pxa168_add_uart(3);
-       pxa168_add_ssp(0);
+       pxa168_add_ssp(1);
        pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
        platform_device_register(&pxa168_device_gpio);
 
index 9b79937d78172e07f9dda2f06386190498f293a1..0e135a599f3e190fa04f94a7b5044431cf52bbb7 100644 (file)
@@ -8,7 +8,7 @@
 #define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000)
 
 #define BANK_OFF(n)    (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)    (GPIO_REGS_VIRT + (x))
+#define GPIO_REG(x)    (*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
 
 #define gpio_to_bank(gpio)     ((gpio) >> 5)
 
index 4285dfd80b6ff30d36eaa378699dc709670e0e8f..4ad3969b98817cc42446d22476aae2ce5771efc6 100644 (file)
@@ -15,6 +15,8 @@ obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
 obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
 
+CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 
index 71de5062c71efd6d86e3e5a4e5927e7dbdf733ea..db81ed531031354b7547c3e48996af1845202c94 100644 (file)
@@ -42,8 +42,8 @@
 
 extern struct sys_timer msm_timer;
 
-static void __init msm7x30_fixup(struct machine_desc *desc, struct tag *tag,
-                        char **cmdline, struct meminfo *mi)
+static void __init msm7x30_fixup(struct tag *tag, char **cmdline,
+               struct meminfo *mi)
 {
        for (; tag->hdr.size; tag = tag_next(tag))
                if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) {
index b04468e7d00e5b1663c9832bc3f5f5ad51e329b5..6dc1cbd2a595b559824dc485a1e0bb74e880d93a 100644 (file)
@@ -32,8 +32,8 @@
 
 #include "devices.h"
 
-static void __init msm8960_fixup(struct machine_desc *desc, struct tag *tag,
-                        char **cmdline, struct meminfo *mi)
+static void __init msm8960_fixup(struct tag *tag, char **cmdline,
+               struct meminfo *mi)
 {
        for (; tag->hdr.size; tag = tag_next(tag))
                if (tag->hdr.tag == ATAG_MEM &&
index cf38e2284fa956437ea3161f92c5fb1be09e147c..44bf71688373b4af31907f744b28f7765f150e75 100644 (file)
@@ -28,8 +28,8 @@
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
-static void __init msm8x60_fixup(struct machine_desc *desc, struct tag *tag,
-                        char **cmdline, struct meminfo *mi)
+static void __init msm8x60_fixup(struct tag *tag, char **cmdline,
+               struct meminfo *mi)
 {
        for (; tag->hdr.size; tag = tag_next(tag))
                if (tag->hdr.tag == ATAG_MEM &&
index 232f97a045041cdd98e53e9f04dc6c2aaebc7f36..bafabb502580e87cd4473e2261582bd796404897 100644 (file)
@@ -180,6 +180,9 @@ static u32 smc(u32 cmd_addr)
                        __asmeq("%1", "r0")
                        __asmeq("%2", "r1")
                        __asmeq("%3", "r2")
+#ifdef REQUIRES_SEC
+                       ".arch_extension sec\n"
+#endif
                        "smc    #0      @ switch to secure world\n"
                        : "=r" (r0)
                        : "r" (r0), "r" (r1), "r" (r2)
index 2aacf41c48e7d3fd02f38a6e80ee9f6087953bf6..4cb276977190e98174c70419a64a63696179ac73 100644 (file)
@@ -1281,9 +1281,9 @@ DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
        NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
 
 DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
-       NULL, NULL, &ipg_clk, NULL);
+       NULL, NULL, &ipg_perclk, NULL);
 DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
-       NULL, NULL, &ipg_clk, NULL);
+       NULL, NULL, &ipg_perclk, NULL);
 
 /* I2C */
 DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -1634,6 +1634,7 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
        return 0;
 }
 
+#ifdef CONFIG_OF
 static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
                                   unsigned long *ckih1, unsigned long *ckih2)
 {
@@ -1671,3 +1672,4 @@ int __init mx53_clocks_init_dt(void)
        clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
        return mx53_clocks_init(ckil, osc, ckih1, ckih2);
 }
+#endif
index 5c5328257dca2f5560ccaa33bf98a27b80582b27..5e2e7a8438606f43015d90115046e555eee1a3c5 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static int mx5_cpu_rev = -1;
 
@@ -67,7 +67,8 @@ static int __init mx51_neon_fixup(void)
        if (!cpu_is_mx51())
                return 0;
 
-       if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) {
+       if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
+                       (elf_hwcap & HWCAP_NEON)) {
                elf_hwcap &= ~HWCAP_NEON;
                pr_info("Turning off NEON support, detected broken NEON implementation\n");
        }
index 26eacc9d0d90fbf88930bd6a009c58efe6914c70..df4a508f240a04a47ce8bb5abbf6074f843c8aae 100644 (file)
@@ -23,7 +23,9 @@
 
 static void imx5_idle(void)
 {
-       mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+       if (!need_resched())
+               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+       local_irq_enable();
 }
 
 /*
@@ -89,7 +91,7 @@ void __init imx51_init_early(void)
        mxc_set_cpu_type(MXC_CPU_MX51);
        mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
        mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-       imx_idle = imx5_idle;
+       pm_idle = imx5_idle;
 }
 
 void __init imx53_init_early(void)
index 229ae3494216da2920bddb5164d66ce523a6ddeb..df0ad3ce234bfa07f592b06af05358881235a6ae 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/clkdev.h>
+#include <linux/spinlock.h>
 
 #include <asm/clkdev.h>
 #include <asm/div64.h>
@@ -29,6 +30,7 @@
 #include <mach/mx28.h>
 #include <mach/common.h>
 #include <mach/clock.h>
+#include <mach/digctl.h>
 
 #include "regs-clkctrl-mx28.h"
 
@@ -43,6 +45,33 @@ static struct clk emi_clk;
 static struct clk saif0_clk;
 static struct clk saif1_clk;
 static struct clk clk32k_clk;
+static DEFINE_SPINLOCK(clkmux_lock);
+
+/*
+ * HW_SAIF_CLKMUX_SEL:
+ *  DIRECT(0x0): SAIF0 clock pins selected for SAIF0 input clocks, and SAIF1
+ *             clock pins selected for SAIF1 input clocks.
+ *  CROSSINPUT(0x1): SAIF1 clock inputs selected for SAIF0 input clocks, and
+ *             SAIF0 clock inputs selected for SAIF1 input clocks.
+ *  EXTMSTR0(0x2): SAIF0 clock pin selected for both SAIF0 and SAIF1 input
+ *             clocks.
+ *  EXTMSTR1(0x3): SAIF1 clock pin selected for both SAIF0 and SAIF1 input
+ *             clocks.
+ */
+int mxs_saif_clkmux_select(unsigned int clkmux)
+{
+       if (clkmux > 0x3)
+               return -EINVAL;
+
+       spin_lock(&clkmux_lock);
+       __raw_writel(BM_DIGCTL_CTRL_SAIF_CLKMUX,
+                       DIGCTRL_BASE_ADDR + HW_DIGCTL_CTRL + MXS_CLR_ADDR);
+       __raw_writel(clkmux << BP_DIGCTL_CTRL_SAIF_CLKMUX,
+                       DIGCTRL_BASE_ADDR + HW_DIGCTL_CTRL + MXS_SET_ADDR);
+       spin_unlock(&clkmux_lock);
+
+       return 0;
+}
 
 static int _raw_clk_enable(struct clk *clk)
 {
@@ -404,7 +433,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate)             \
        reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);         \
        reg &= ~BM_CLKCTRL_##dr##_DIV;                                  \
        reg |= div << BP_CLKCTRL_##dr##_DIV;                            \
-       if (reg | (1 << clk->enable_shift)) {                           \
+       if (reg & (1 << clk->enable_shift)) {                           \
                pr_err("%s: clock is gated\n", __func__);               \
                return -EINVAL;                                         \
        }                                                               \
@@ -785,6 +814,15 @@ int __init mx28_clocks_init(void)
        clk_set_parent(&saif0_clk, &pll0_clk);
        clk_set_parent(&saif1_clk, &pll0_clk);
 
+       /*
+        * Set an initial clock rate for the saif internal logic to work
+        * properly. This is important when working in EXTMASTER mode that
+        * uses the other saif's BITCLK&LRCLK but it still needs a basic
+        * clock which should be fast enough for the internal logic.
+        */
+       clk_set_rate(&saif0_clk, 24000000);
+       clk_set_rate(&saif1_clk, 24000000);
+
        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
        mxs_timer_init(&clk32k_clk, MX28_INT_TIMER0);
index c8887103f0e32670b043d948d60f6b0fc915cecb..4f50094e293d35aa9cd28e980ae647e63c0beb8c 100644 (file)
@@ -47,6 +47,7 @@ struct platform_device *__init mx28_add_mxsfb(
                const struct mxsfb_platform_data *pdata);
 
 extern const struct mxs_saif_data mx28_saif_data[] __initconst;
-#define mx28_add_saif(id)              mxs_add_saif(&mx28_saif_data[id])
+#define mx28_add_saif(id, pdata) \
+       mxs_add_saif(&mx28_saif_data[id], pdata)
 
 struct platform_device *__init mx28_add_rtc_stmp3xxx(void);
index 1ec965e9fe92e6e14c98b3bbc4787966136dbfa4..f6e3a60b4201f1efc379a76c89e03e072cb81ac0 100644 (file)
@@ -32,7 +32,8 @@ const struct mxs_saif_data mx28_saif_data[] __initconst = {
 };
 #endif
 
-struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data)
+struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data,
+                               const struct mxs_saif_platform_data *pdata)
 {
        struct resource res[] = {
                {
@@ -56,5 +57,5 @@ struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data)
        };
 
        return mxs_add_platform_device("mxs-saif", data->id, res,
-                                       ARRAY_SIZE(res), NULL, 0);
+                               ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
index 635bb5d9a20ade988bfa61667b9513c985a47bb9..3bbb94f4bbe12a430cebebce77bc3a608f300b68 100644 (file)
@@ -16,6 +16,7 @@ struct clk;
 extern const u32 *mxs_get_ocotp(void);
 extern int mxs_reset_block(void __iomem *);
 extern void mxs_timer_init(struct clk *, int);
+extern int mxs_saif_clkmux_select(unsigned int clkmux);
 
 extern int mx23_register_gpios(void);
 extern int mx23_clocks_init(void);
index a8080f44c03d9310d74b26d2965dba0862f006f1..dc369c1239fc3eac5a1c7d27968a3bf5c27f3912 100644 (file)
@@ -94,6 +94,7 @@ struct platform_device *__init mxs_add_mxs_pwm(
                resource_size_t iobase, int id);
 
 /* saif */
+#include <sound/saif.h>
 struct mxs_saif_data {
        int id;
        resource_size_t iobase;
@@ -103,4 +104,5 @@ struct mxs_saif_data {
 };
 
 struct platform_device *__init mxs_add_saif(
-               const struct mxs_saif_data *data);
+               const struct mxs_saif_data *data,
+               const struct mxs_saif_platform_data *pdata);
diff --git a/arch/arm/mach-mxs/include/mach/digctl.h b/arch/arm/mach-mxs/include/mach/digctl.h
new file mode 100644 (file)
index 0000000..49a888c
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MACH_DIGCTL_H__
+#define __MACH_DIGCTL_H__
+
+/* MXS DIGCTL SAIF CLKMUX */
+#define MXS_DIGCTL_SAIF_CLKMUX_DIRECT          0x0
+#define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT      0x1
+#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0                0x2
+#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1                0x3
+
+#define HW_DIGCTL_CTRL                 0x0
+#define  BP_DIGCTL_CTRL_SAIF_CLKMUX    10
+#define  BM_DIGCTL_CTRL_SAIF_CLKMUX    (0x3 << 10)
+#endif
index ac2316d53d3c8dd3d173147eda9cfbf4b5e5f47b..ac84a10baa14c5c4a3b294047b7b7dc75a1fa9ec 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <mach/common.h>
 #include <mach/iomux-mx28.h>
+#include <mach/digctl.h>
 
 #include "devices-mx28.h"
 
@@ -421,6 +422,18 @@ static struct gpio mx28evk_lcd_gpios[] = {
        { MX28EVK_BL_ENABLE, GPIOF_OUT_INIT_HIGH, "bl-enable" },
 };
 
+static const struct mxs_saif_platform_data
+                       mx28evk_mxs_saif_pdata[] __initconst = {
+       /* working on EXTMSTR0 mode (saif0 master, saif1 slave) */
+       {
+               .master_mode = 1,
+               .master_id = 0,
+       }, {
+               .master_mode = 0,
+               .master_id = 0,
+       },
+};
+
 static void __init mx28evk_init(void)
 {
        int ret;
@@ -454,8 +467,9 @@ static void __init mx28evk_init(void)
        else
                mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
 
-       mx28_add_saif(0);
-       mx28_add_saif(1);
+       mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
+       mx28_add_saif(0, &mx28evk_mxs_saif_pdata[0]);
+       mx28_add_saif(1, &mx28evk_mxs_saif_pdata[1]);
 
        mx28_add_mxs_i2c(0);
        i2c_register_board_info(0, mxs_i2c0_board_info,
@@ -471,7 +485,8 @@ static void __init mx28evk_init(void)
                               "mmc0-slot-power");
        if (ret)
                pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret);
-       mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
+       else
+               mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
 
        ret = gpio_request_one(MX28EVK_MMC1_SLOT_POWER, GPIOF_OUT_INIT_LOW,
                               "mmc1-slot-power");
@@ -480,7 +495,6 @@ static void __init mx28evk_init(void)
        else
                mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
 
-       mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
        mx28_add_rtc_stmp3xxx();
 
        gpio_led_register_device(0, &mx28evk_led_data);
index e0a028161ddee89a4119014ed83420bd0a21ad4e..73f287d6429b629d57f7c093645962ce48cee318 100644 (file)
@@ -171,14 +171,6 @@ config MACH_OMAP_GENERIC
 comment "OMAP CPU Speed"
        depends on ARCH_OMAP1
 
-config OMAP_CLOCKS_SET_BY_BOOTLOADER
-       bool "OMAP clocks set by bootloader"
-       depends on ARCH_OMAP1
-       help
-         Enable this option to prevent the kernel from overriding the clock
-         frequencies programmed by bootloader for MPU, DSP, MMUs, TC,
-         internal LCD controller and MPU peripherals.
-
 config OMAP_ARM_216MHZ
        bool "OMAP ARM 216 MHz CPU (1710 only)"
         depends on ARCH_OMAP1 && ARCH_OMAP16XX
index 51bae31cf361289e5f2711ad46a41afd4b01b09c..b0f15d234a12b4ad9dd1beb34da7df187e3f86b4 100644 (file)
@@ -302,8 +302,6 @@ static void __init ams_delta_init(void)
        omap_cfg_reg(J19_1610_CAM_D6);
        omap_cfg_reg(J18_1610_CAM_D7);
 
-       iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
-
        omap_board_config = ams_delta_config;
        omap_board_config_size = ARRAY_SIZE(ams_delta_config);
        omap_serial_init();
@@ -373,10 +371,16 @@ static int __init ams_delta_modem_init(void)
 }
 arch_initcall(ams_delta_modem_init);
 
+static void __init ams_delta_map_io(void)
+{
+       omap15xx_map_io();
+       iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
+}
+
 MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
        /* Maintainer: Jonathan McDowell <noodles@earth.li> */
        .atag_offset    = 0x100,
-       .map_io         = omap15xx_map_io,
+       .map_io         = ams_delta_map_io,
        .init_early     = omap1_init_early,
        .reserve        = omap_reserve,
        .init_irq       = omap1_init_irq,
index c6fe61dfe856b9a42739c4b11b4e6a4d8e486b72..42061573e3803b449a314d1c0ccc0553371f854b 100644 (file)
@@ -42,7 +42,6 @@
 #include <plat/irda.h>
 #include <plat/keypad.h>
 #include <plat/common.h>
-#include <plat/omap-alsa.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
index eaf09efb91caec613eeb73e961e7fbd77a93cf21..16b1423b454a32dea7197460a393b12a4bd4e2b0 100644 (file)
@@ -17,7 +17,8 @@
 
 #include <plat/clock.h>
 
-extern int __init omap1_clk_init(void);
+int omap1_clk_init(void);
+void omap1_clk_late_init(void);
 extern int omap1_clk_enable(struct clk *clk);
 extern void omap1_clk_disable(struct clk *clk);
 extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate);
index 92400b9eb69f10c419c7e1295e238d56d5ef6110..1297bb58869cf72dcda88e7329b9f83f5cd3da13 100644 (file)
@@ -767,6 +767,15 @@ static struct clk_functions omap1_clk_functions = {
        .clk_disable_unused     = omap1_clk_disable_unused,
 };
 
+static void __init omap1_show_rates(void)
+{
+       pr_notice("Clocking rate (xtal/DPLL1/MPU): "
+                       "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
+               ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
+               ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+               arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
+}
+
 int __init omap1_clk_init(void)
 {
        struct omap_clk *c;
@@ -835,9 +844,12 @@ int __init omap1_clk_init(void)
        /* We want to be in syncronous scalable mode */
        omap_writew(0x1000, ARM_SYSST);
 
-#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
-       /* Use values set by bootloader. Determine PLL rate and recalculate
-        * dependent clocks as if kernel had changed PLL or divisors.
+
+       /*
+        * Initially use the values set by bootloader. Determine PLL rate and
+        * recalculate dependent clocks as if kernel had changed PLL or
+        * divisors. See also omap1_clk_late_init() that can reprogram dpll1
+        * after the SRAM is initialized.
         */
        {
                unsigned pll_ctl_val = omap_readw(DPLL_CTL);
@@ -862,25 +874,10 @@ int __init omap1_clk_init(void)
                        }
                }
        }
-#else
-       /* Find the highest supported frequency and enable it */
-       if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
-               printk(KERN_ERR "System frequencies not set. Check your config.\n");
-               /* Guess sane values (60MHz) */
-               omap_writew(0x2290, DPLL_CTL);
-               omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
-               ck_dpll1.rate = 60000000;
-       }
-#endif
        propagate_rate(&ck_dpll1);
        /* Cache rates for clocks connected to ck_ref (not dpll1) */
        propagate_rate(&ck_ref);
-       printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
-               "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
-              ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
-              ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
-              arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
-
+       omap1_show_rates();
        if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
                /* Select slicer output as OMAP input clock */
                omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1,
@@ -925,3 +922,21 @@ int __init omap1_clk_init(void)
 
        return 0;
 }
+
+#define OMAP1_DPLL1_SANE_VALUE 60000000
+
+void __init omap1_clk_late_init(void)
+{
+       if (ck_dpll1.rate >= OMAP1_DPLL1_SANE_VALUE)
+               return;
+
+       /* Find the highest supported frequency and enable it */
+       if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
+               pr_err("System frequencies not set, using default. Check your config.\n");
+               omap_writew(0x2290, DPLL_CTL);
+               omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
+               ck_dpll1.rate = OMAP1_DPLL1_SANE_VALUE;
+       }
+       propagate_rate(&ck_dpll1);
+       omap1_show_rates();
+}
index 48ef9888e820e5d95ecbd61274d2904a712ce63f..475cb2f50d872f326325991b76d0c5348aa5cfd2 100644 (file)
@@ -30,6 +30,8 @@
 #include <plat/omap7xx.h>
 #include <plat/mcbsp.h>
 
+#include "clock.h"
+
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE)
@@ -293,6 +295,7 @@ static int __init omap1_init_devices(void)
                return -ENODEV;
 
        omap_sram_init();
+       omap1_clk_late_init();
 
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
index 495b3987d461f840434d547977c716ce1cc8149d..89ea20ca0cccbc02c0ccba365547942e8c41ea93 100644 (file)
@@ -116,7 +116,7 @@ void omap1_pm_idle(void)
                return;
        }
 
-#ifdef CONFIG_OMAP_MPU_TIMER
+#if defined(CONFIG_OMAP_MPU_TIMER) && !defined(CONFIG_OMAP_DM_TIMER)
 #warning Enable 32kHz OS timer in order to allow sleep states in idle
        use_idlect1 = use_idlect1 & ~(1 << 9);
 #else
index 503414718905862d12e104b7940bfc7dc1524971..e1293aa513d338fe19ffd7990b189109b7ca0787 100644 (file)
@@ -334,6 +334,7 @@ config MACH_OMAP4_PANDA
 config OMAP3_EMU
        bool "OMAP3 debugging peripherals"
        depends on ARCH_OMAP3
+       select ARM_AMBA
        select OC_ETM
        help
          Say Y here to enable debugging hardware of omap3
index 69ab1c069134ccee42da01c015aea9d219408f4a..b009f17dee5606de2acbb1b7ba25c8938d0c5adb 100644 (file)
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
-        common.o gpio.o dma.o wd_timer.o
+        common.o gpio.o dma.o wd_timer.o display.o
 
 omap-2-3-common                                = irq.o sdrc.o
 hwmod-common                           = omap_hwmod.o \
@@ -264,7 +264,4 @@ smsc911x-$(CONFIG_SMSC911X)         := gpmc-smsc911x.o
 obj-y                                  += $(smsc911x-m) $(smsc911x-y)
 obj-$(CONFIG_ARCH_OMAP4)               += hwspinlock.o
 
-disp-$(CONFIG_OMAP2_DSS)               := display.o
-obj-y                                  += $(disp-m) $(disp-y)
-
 obj-y                                  += common-board-devices.o twl-common.o
index 42918940c530ac5264960a808ec4fdfc117ece25..90154e411da0f27c2850fa4075ba44255bda7eb4 100644 (file)
@@ -226,7 +226,6 @@ static int devkit8000_twl_gpio_setup(struct device *dev,
 {
        int ret;
 
-       omap_mux_init_gpio(29, OMAP_PIN_INPUT);
        /* gpio + 0 is "mmc0_cd" (input/IRQ) */
        mmc[0].gpio_cd = gpio + 0;
        omap2_hsmmc_init(mmc);
index 0cc9094e5ee046afe40095bce2dc1cbd09d52264..fb55fa3dad5ae6d94cd76b4085b08f12aa07da2e 100644 (file)
@@ -28,6 +28,7 @@
  * XXX: Still needed to boot until the i2c & twl driver is adapted to
  * device-tree
  */
+#ifdef CONFIG_ARCH_OMAP4
 static struct twl4030_platform_data sdp4430_twldata = {
        .irq_base       = TWL6030_IRQ_BASE,
        .irq_end        = TWL6030_IRQ_END,
@@ -37,7 +38,9 @@ static void __init omap4_i2c_init(void)
 {
        omap4_pmic_init("twl6030", &sdp4430_twldata);
 }
+#endif
 
+#ifdef CONFIG_ARCH_OMAP3
 static struct twl4030_platform_data beagle_twldata = {
        .irq_base       = TWL4030_IRQ_BASE,
        .irq_end        = TWL4030_IRQ_END,
@@ -47,6 +50,7 @@ static void __init omap3_i2c_init(void)
 {
        omap3_pmic_init("twl4030", &beagle_twldata);
 }
+#endif
 
 static struct of_device_id omap_dt_match_table[] __initdata = {
        { .compatible = "simple-bus", },
@@ -72,17 +76,21 @@ static void __init omap_generic_init(void)
        of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
 }
 
+#ifdef CONFIG_ARCH_OMAP4
 static void __init omap4_init(void)
 {
        omap4_i2c_init();
        omap_generic_init();
 }
+#endif
 
+#ifdef CONFIG_ARCH_OMAP3
 static void __init omap3_init(void)
 {
        omap3_i2c_init();
        omap_generic_init();
 }
+#endif
 
 #if defined(CONFIG_SOC_OMAP2420)
 static const char *omap242x_boards_compat[] __initdata = {
index c12666ee7017a8880ff9cfd151b9a1e5d7ba77b3..8b351d92a1cce289cf1af4eba51577b788f5b602 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/input/matrix_keypad.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -34,7 +35,6 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/keypad.h>
 #include <plat/menelaus.h>
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 
 #define H4_ETHR_GPIO_IRQ               92
 
-static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
-static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
-
-static const unsigned int h4_keymap[] = {
+#if defined(CONFIG_KEYBOARD_MATRIX) || defined(CONFIG_KEYBOARD_MATRIX_MODULE)
+static const uint32_t board_matrix_keys[] = {
        KEY(0, 0, KEY_LEFT),
        KEY(1, 0, KEY_RIGHT),
        KEY(2, 0, KEY_A),
@@ -86,6 +84,71 @@ static const unsigned int h4_keymap[] = {
        KEY(4, 5, KEY_ENTER),
 };
 
+static const struct matrix_keymap_data board_keymap_data = {
+       .keymap                 = board_matrix_keys,
+       .keymap_size            = ARRAY_SIZE(board_matrix_keys),
+};
+
+static unsigned int board_keypad_row_gpios[] = {
+       88, 89, 124, 11, 6, 96
+};
+
+static unsigned int board_keypad_col_gpios[] = {
+       90, 91, 100, 36, 12, 97, 98
+};
+
+static struct matrix_keypad_platform_data board_keypad_platform_data = {
+       .keymap_data    = &board_keymap_data,
+       .row_gpios      = board_keypad_row_gpios,
+       .num_row_gpios  = ARRAY_SIZE(board_keypad_row_gpios),
+       .col_gpios      = board_keypad_col_gpios,
+       .num_col_gpios  = ARRAY_SIZE(board_keypad_col_gpios),
+       .active_low     = 1,
+
+       .debounce_ms            = 20,
+       .col_scan_delay_us      = 5,
+};
+
+static struct platform_device board_keyboard = {
+       .name   = "matrix-keypad",
+       .id     = -1,
+       .dev    = {
+               .platform_data = &board_keypad_platform_data,
+       },
+};
+static void __init board_mkp_init(void)
+{
+       omap_mux_init_gpio(88, OMAP_PULL_ENA | OMAP_PULL_UP);
+       omap_mux_init_gpio(89, OMAP_PULL_ENA | OMAP_PULL_UP);
+       omap_mux_init_gpio(124, OMAP_PULL_ENA | OMAP_PULL_UP);
+       omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
+       if (omap_has_menelaus()) {
+               omap_mux_init_signal("sdrc_a14.gpio0",
+                       OMAP_PULL_ENA | OMAP_PULL_UP);
+               omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
+               omap_mux_init_signal("gpio_98", 0);
+               board_keypad_row_gpios[5] = 0;
+               board_keypad_col_gpios[2] = 15;
+               board_keypad_col_gpios[6] = 18;
+       } else {
+               omap_mux_init_signal("gpio_96", OMAP_PULL_ENA | OMAP_PULL_UP);
+               omap_mux_init_signal("gpio_100", 0);
+               omap_mux_init_signal("gpio_98", 0);
+       }
+       omap_mux_init_signal("gpio_90", 0);
+       omap_mux_init_signal("gpio_91", 0);
+       omap_mux_init_signal("gpio_36", 0);
+       omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
+       omap_mux_init_signal("gpio_97", 0);
+
+       platform_device_register(&board_keyboard);
+}
+#else
+static inline void board_mkp_init(void)
+{
+}
+#endif
+
 static struct mtd_partition h4_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
@@ -137,31 +200,8 @@ static struct platform_device h4_flash_device = {
        .resource       = &h4_flash_resource,
 };
 
-static const struct matrix_keymap_data h4_keymap_data = {
-       .keymap         = h4_keymap,
-       .keymap_size    = ARRAY_SIZE(h4_keymap),
-};
-
-static struct omap_kp_platform_data h4_kp_data = {
-       .rows           = 6,
-       .cols           = 7,
-       .keymap_data    = &h4_keymap_data,
-       .rep            = true,
-       .row_gpios      = row_gpios,
-       .col_gpios      = col_gpios,
-};
-
-static struct platform_device h4_kp_device = {
-       .name           = "omap-keypad",
-       .id             = -1,
-       .dev            = {
-               .platform_data = &h4_kp_data,
-       },
-};
-
 static struct platform_device *h4_devices[] __initdata = {
        &h4_flash_device,
-       &h4_kp_device,
 };
 
 static struct panel_generic_dpi_data h4_panel_data = {
@@ -336,31 +376,7 @@ static void __init omap_h4_init(void)
         * if not needed.
         */
 
-#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
-       omap_mux_init_gpio(88, OMAP_PULL_ENA | OMAP_PULL_UP);
-       omap_mux_init_gpio(89, OMAP_PULL_ENA | OMAP_PULL_UP);
-       omap_mux_init_gpio(124, OMAP_PULL_ENA | OMAP_PULL_UP);
-       omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
-       if (omap_has_menelaus()) {
-               omap_mux_init_signal("sdrc_a14.gpio0",
-                       OMAP_PULL_ENA | OMAP_PULL_UP);
-               omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
-               omap_mux_init_signal("gpio_98", 0);
-               row_gpios[5] = 0;
-               col_gpios[2] = 15;
-               col_gpios[6] = 18;
-       } else {
-               omap_mux_init_signal("gpio_96", OMAP_PULL_ENA | OMAP_PULL_UP);
-               omap_mux_init_signal("gpio_100", 0);
-               omap_mux_init_signal("gpio_98", 0);
-       }
-       omap_mux_init_signal("gpio_90", 0);
-       omap_mux_init_signal("gpio_91", 0);
-       omap_mux_init_signal("gpio_36", 0);
-       omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
-       omap_mux_init_signal("gpio_97", 0);
-#endif
-
+       board_mkp_init();
        i2c_register_board_info(1, h4_i2c_board_info,
                        ARRAY_SIZE(h4_i2c_board_info));
 
index bcffee001bfa424c6f5a029292ef11e84f3f3eca..e069a9be93dfe0e9aafc3411e560de700529e13a 100644 (file)
                                         (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
 
 /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
-#define DPLL_FINT_BAND1_MIN            750000
-#define DPLL_FINT_BAND1_MAX            2100000
-#define DPLL_FINT_BAND2_MIN            7500000
-#define DPLL_FINT_BAND2_MAX            21000000
+#define OMAP3430_DPLL_FINT_BAND1_MIN   750000
+#define OMAP3430_DPLL_FINT_BAND1_MAX   2100000
+#define OMAP3430_DPLL_FINT_BAND2_MIN   7500000
+#define OMAP3430_DPLL_FINT_BAND2_MAX   21000000
+
+/*
+ * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
+ * From device data manual section 4.3 "DPLL and DLL Specifications".
+ */
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN  500000
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX  2500000
+#define OMAP3PLUS_DPLL_FINT_MIN                32000
+#define OMAP3PLUS_DPLL_FINT_MAX                52000000
 
 /* _dpll_test_fint() return codes */
 #define DPLL_FINT_UNDERFLOW            -1
 static int _dpll_test_fint(struct clk *clk, u8 n)
 {
        struct dpll_data *dd;
-       long fint;
+       long fint, fint_min, fint_max;
        int ret = 0;
 
        dd = clk->dpll_data;
 
        /* DPLL divider must result in a valid jitter correction val */
        fint = clk->parent->rate / n;
-       if (fint < DPLL_FINT_BAND1_MIN) {
 
+       if (cpu_is_omap24xx()) {
+               /* Should not be called for OMAP2, so warn if it is called */
+               WARN(1, "No fint limits available for OMAP2!\n");
+               return DPLL_FINT_INVALID;
+       } else if (cpu_is_omap3430()) {
+               fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
+               fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
+       } else if (dd->flags & DPLL_J_TYPE) {
+               fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
+               fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
+       } else {
+               fint_min = OMAP3PLUS_DPLL_FINT_MIN;
+               fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+       }
+
+       if (fint < fint_min) {
                pr_debug("rejecting n=%d due to Fint failure, "
                         "lowering max_divider\n", n);
                dd->max_divider = n;
                ret = DPLL_FINT_UNDERFLOW;
-
-       } else if (fint > DPLL_FINT_BAND1_MAX &&
-                  fint < DPLL_FINT_BAND2_MIN) {
-
-               pr_debug("rejecting n=%d due to Fint failure\n", n);
-               ret = DPLL_FINT_INVALID;
-
-       } else if (fint > DPLL_FINT_BAND2_MAX) {
-
+       } else if (fint > fint_max) {
                pr_debug("rejecting n=%d due to Fint failure, "
                         "boosting min_divider\n", n);
                dd->min_divider = n;
                ret = DPLL_FINT_INVALID;
-
+       } else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX &&
+                  fint < OMAP3430_DPLL_FINT_BAND2_MIN) {
+               pr_debug("rejecting n=%d due to Fint failure\n", n);
+               ret = DPLL_FINT_INVALID;
        }
 
        return ret;
index 48ac568881bd4de531808d092356b440687b9fee..2311bc2172264248aa181f75fb579c6e6b218fbd 100644 (file)
@@ -66,6 +66,8 @@ void omap3_noncore_dpll_disable(struct clk *clk);
 int omap4_dpllmx_gatectrl_read(struct clk *clk);
 void omap4_dpllmx_allow_gatectrl(struct clk *clk);
 void omap4_dpllmx_deny_gatectrl(struct clk *clk);
+long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
 void omap2_clk_disable_unused(struct clk *clk);
index 14a6277dd184c0e27323efbd1cef5161c3c60562..61ad3855f10a61e479e994d547e9d0955aed166d 100644 (file)
@@ -1898,18 +1898,6 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "pka_ick",      &pka_ick,       CK_242X),
        CLK(NULL,       "usb_fck",      &usb_fck,       CK_242X),
        CLK("musb-hdrc",        "fck",  &osc_ck,        CK_242X),
-       CLK("omap_timer.1",     "fck",  &gpt1_fck,      CK_242X),
-       CLK("omap_timer.2",     "fck",  &gpt2_fck,      CK_242X),
-       CLK("omap_timer.3",     "fck",  &gpt3_fck,      CK_242X),
-       CLK("omap_timer.4",     "fck",  &gpt4_fck,      CK_242X),
-       CLK("omap_timer.5",     "fck",  &gpt5_fck,      CK_242X),
-       CLK("omap_timer.6",     "fck",  &gpt6_fck,      CK_242X),
-       CLK("omap_timer.7",     "fck",  &gpt7_fck,      CK_242X),
-       CLK("omap_timer.8",     "fck",  &gpt8_fck,      CK_242X),
-       CLK("omap_timer.9",     "fck",  &gpt9_fck,      CK_242X),
-       CLK("omap_timer.10",    "fck",  &gpt10_fck,     CK_242X),
-       CLK("omap_timer.11",    "fck",  &gpt11_fck,     CK_242X),
-       CLK("omap_timer.12",    "fck",  &gpt12_fck,     CK_242X),
        CLK("omap_timer.1",     "32k_ck",       &func_32k_ck,   CK_243X),
        CLK("omap_timer.2",     "32k_ck",       &func_32k_ck,   CK_243X),
        CLK("omap_timer.3",     "32k_ck",       &func_32k_ck,   CK_243X),
index ea6717cfa3c84245b390502349eb262850e7df23..0cc12879e7b955b1bee0e256e597d34c42b51f57 100644 (file)
@@ -1998,18 +1998,6 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "mdm_intc_ick", &mdm_intc_ick,  CK_243X),
        CLK("omap_hsmmc.0", "mmchsdb_fck",      &mmchsdb1_fck,  CK_243X),
        CLK("omap_hsmmc.1", "mmchsdb_fck",      &mmchsdb2_fck,  CK_243X),
-       CLK("omap_timer.1",     "fck",  &gpt1_fck,      CK_243X),
-       CLK("omap_timer.2",     "fck",  &gpt2_fck,      CK_243X),
-       CLK("omap_timer.3",     "fck",  &gpt3_fck,      CK_243X),
-       CLK("omap_timer.4",     "fck",  &gpt4_fck,      CK_243X),
-       CLK("omap_timer.5",     "fck",  &gpt5_fck,      CK_243X),
-       CLK("omap_timer.6",     "fck",  &gpt6_fck,      CK_243X),
-       CLK("omap_timer.7",     "fck",  &gpt7_fck,      CK_243X),
-       CLK("omap_timer.8",     "fck",  &gpt8_fck,      CK_243X),
-       CLK("omap_timer.9",     "fck",  &gpt9_fck,      CK_243X),
-       CLK("omap_timer.10",    "fck",  &gpt10_fck,     CK_243X),
-       CLK("omap_timer.11",    "fck",  &gpt11_fck,     CK_243X),
-       CLK("omap_timer.12",    "fck",  &gpt12_fck,     CK_243X),
        CLK("omap_timer.1",     "32k_ck",  &func_32k_ck,   CK_243X),
        CLK("omap_timer.2",     "32k_ck",  &func_32k_ck,   CK_243X),
        CLK("omap_timer.3",     "32k_ck",  &func_32k_ck,   CK_243X),
index 65dd363163bccdfa6890b112458aac36e1b7f704..5d0064a4fb5a638bb1141489354244e95899c1a1 100644 (file)
@@ -3464,18 +3464,6 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK("musb-am35x",       "fck",          &hsotgusb_fck_am35xx,   CK_AM35XX),
        CLK(NULL,       "hecc_ck",      &hecc_ck,       CK_AM35XX),
        CLK(NULL,       "uart4_ick",    &uart4_ick_am35xx,      CK_AM35XX),
-       CLK("omap_timer.1",     "fck",  &gpt1_fck,      CK_3XXX),
-       CLK("omap_timer.2",     "fck",  &gpt2_fck,      CK_3XXX),
-       CLK("omap_timer.3",     "fck",  &gpt3_fck,      CK_3XXX),
-       CLK("omap_timer.4",     "fck",  &gpt4_fck,      CK_3XXX),
-       CLK("omap_timer.5",     "fck",  &gpt5_fck,      CK_3XXX),
-       CLK("omap_timer.6",     "fck",  &gpt6_fck,      CK_3XXX),
-       CLK("omap_timer.7",     "fck",  &gpt7_fck,      CK_3XXX),
-       CLK("omap_timer.8",     "fck",  &gpt8_fck,      CK_3XXX),
-       CLK("omap_timer.9",     "fck",  &gpt9_fck,      CK_3XXX),
-       CLK("omap_timer.10",    "fck",  &gpt10_fck,     CK_3XXX),
-       CLK("omap_timer.11",    "fck",  &gpt11_fck,     CK_3XXX),
-       CLK("omap_timer.12",    "fck",  &gpt12_fck,     CK_3XXX),
        CLK("omap_timer.1",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
        CLK("omap_timer.2",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
        CLK("omap_timer.3",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
index 7ceb870e7ab8d6abf330227c0f266eb8aef03561..287a46f78d976c5002207581370676e2680b8dce 100644 (file)
@@ -8,6 +8,13 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
 
+/*
+ * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is
+ *    set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM
+ *    vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters")
+ */
+#define OMAP4430_REGM4XEN_MULT 4
+
 int omap4xxx_clk_init(void);
 
 #endif
index 946bf04a956db5638035ea591c262d3944e8a3d2..0798a802497a543dbfc2bff9b71da28772ffa6be 100644 (file)
@@ -270,8 +270,8 @@ static struct clk dpll_abe_ck = {
        .dpll_data      = &dpll_abe_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
-       .recalc         = &omap3_dpll_recalc,
-       .round_rate     = &omap2_dpll_round_rate,
+       .recalc         = &omap4_dpll_regm4xen_recalc,
+       .round_rate     = &omap4_dpll_regm4xen_round_rate,
        .set_rate       = &omap3_noncore_dpll_set_rate,
 };
 
@@ -1195,11 +1195,25 @@ static struct clk l4_wkup_clk_mux_ck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
+static const struct clksel_rate div2_2to1_rates[] = {
+       { .div = 1, .val = 1, .flags = RATE_IN_4430 },
+       { .div = 2, .val = 0, .flags = RATE_IN_4430 },
+       { .div = 0 },
+};
+
+static const struct clksel ocp_abe_iclk_div[] = {
+       { .parent = &aess_fclk, .rates = div2_2to1_rates },
+       { .parent = NULL },
+};
+
 static struct clk ocp_abe_iclk = {
        .name           = "ocp_abe_iclk",
        .parent         = &aess_fclk,
+       .clksel         = ocp_abe_iclk_div,
+       .clksel_reg     = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_AESS_FCLK_MASK,
        .ops            = &clkops_null,
-       .recalc         = &followparent_recalc,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk per_abe_24m_fclk = {
@@ -1398,9 +1412,9 @@ static struct clk dss_dss_clk = {
 };
 
 static const struct clksel_rate div3_8to32_rates[] = {
-       { .div = 8, .val = 0, .flags = RATE_IN_44XX },
-       { .div = 16, .val = 1, .flags = RATE_IN_44XX },
-       { .div = 32, .val = 2, .flags = RATE_IN_44XX },
+       { .div = 8, .val = 0, .flags = RATE_IN_4460 },
+       { .div = 16, .val = 1, .flags = RATE_IN_4460 },
+       { .div = 32, .val = 2, .flags = RATE_IN_4460 },
        { .div = 0 },
 };
 
@@ -3363,17 +3377,6 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("usbhs-omap.0",     "usbhost_ick",          &dummy_ck,              CK_443X),
        CLK("usbhs-omap.0",     "usbtll_fck",           &dummy_ck,      CK_443X),
        CLK("omap_wdt", "ick",                          &dummy_ck,      CK_443X),
-       CLK("omap_timer.1",     "fck",                  &timer1_fck,    CK_443X),
-       CLK("omap_timer.2",     "fck",                  &timer2_fck,    CK_443X),
-       CLK("omap_timer.3",     "fck",                  &timer3_fck,    CK_443X),
-       CLK("omap_timer.4",     "fck",                  &timer4_fck,    CK_443X),
-       CLK("omap_timer.5",     "fck",                  &timer5_fck,    CK_443X),
-       CLK("omap_timer.6",     "fck",                  &timer6_fck,    CK_443X),
-       CLK("omap_timer.7",     "fck",                  &timer7_fck,    CK_443X),
-       CLK("omap_timer.8",     "fck",                  &timer8_fck,    CK_443X),
-       CLK("omap_timer.9",     "fck",                  &timer9_fck,    CK_443X),
-       CLK("omap_timer.10",    "fck",                  &timer10_fck,   CK_443X),
-       CLK("omap_timer.11",    "fck",                  &timer11_fck,   CK_443X),
        CLK("omap_timer.1",     "32k_ck",       &sys_32k_ck,    CK_443X),
        CLK("omap_timer.2",     "32k_ck",       &sys_32k_ck,    CK_443X),
        CLK("omap_timer.3",     "32k_ck",       &sys_32k_ck,    CK_443X),
@@ -3403,12 +3406,12 @@ int __init omap4xxx_clk_init(void)
        struct omap_clk *c;
        u32 cpu_clkflg;
 
-       if (cpu_is_omap44xx()) {
+       if (cpu_is_omap443x()) {
                cpu_mask = RATE_IN_4430;
                cpu_clkflg = CK_443X;
        } else if (cpu_is_omap446x()) {
-               cpu_mask = RATE_IN_4460;
-               cpu_clkflg = CK_446X;
+               cpu_mask = RATE_IN_4460 | RATE_IN_4430;
+               cpu_clkflg = CK_446X | CK_443X;
        } else {
                return 0;
        }
index 4bf6e6e8b1001ae5b14ab0e86c44dec7c8b1043d..942bb4f19f9fd6df5af92b1b551cb1a3f3bb2313 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/sched.h>
 #include <linux/cpuidle.h>
+#include <linux/export.h>
 
 #include <plat/prcm.h>
 #include <plat/irqs.h>
@@ -88,17 +89,21 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
- * @state: The target state to be programmed
+ * @drv: cpuidle driver
+ * @index: the index of state to be entered
  *
  * Called from the CPUidle framework to program the device to the
  * specified target state selected by the governor.
  */
 static int omap3_enter_idle(struct cpuidle_device *dev,
-                       struct cpuidle_state *state)
+                               struct cpuidle_driver *drv,
+                               int index)
 {
-       struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
+       struct omap3_idle_statedata *cx =
+                       cpuidle_get_statedata(&dev->states_usage[index]);
        struct timespec ts_preidle, ts_postidle, ts_idle;
        u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
+       int idle_time;
 
        /* Used to keep track of the total time in idle */
        getnstimeofday(&ts_preidle);
@@ -113,7 +118,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
                goto return_sleep_time;
 
        /* Deny idle for C1 */
-       if (state == &dev->states[0]) {
+       if (index == 0) {
                pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
                pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
        }
@@ -122,7 +127,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
        omap_sram_idle();
 
        /* Re-allow idle for C1 */
-       if (state == &dev->states[0]) {
+       if (index == 0) {
                pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
                pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
        }
@@ -134,28 +139,38 @@ return_sleep_time:
        local_irq_enable();
        local_fiq_enable();
 
-       return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
+       idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \
+                                                               USEC_PER_SEC;
+
+       /* Update cpuidle counters */
+       dev->last_residency = idle_time;
+
+       return index;
 }
 
 /**
  * next_valid_state - Find next valid C-state
  * @dev: cpuidle device
- * @state: Currently selected C-state
+ * @drv: cpuidle driver
+ * @index: Index of currently selected c-state
  *
- * If the current state is valid, it is returned back to the caller.
- * Else, this function searches for a lower c-state which is still
- * valid.
+ * If the state corresponding to index is valid, index is returned back
+ * to the caller. Else, this function searches for a lower c-state which is
+ * still valid (as defined in omap3_power_states[]) and returns its index.
  *
  * A state is valid if the 'valid' field is enabled and
  * if it satisfies the enable_off_mode condition.
  */
-static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
-                                             struct cpuidle_state *curr)
+static int next_valid_state(struct cpuidle_device *dev,
+                       struct cpuidle_driver *drv,
+                               int index)
 {
-       struct cpuidle_state *next = NULL;
-       struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
+       struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
+       struct cpuidle_state *curr = &drv->states[index];
+       struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
        u32 mpu_deepest_state = PWRDM_POWER_RET;
        u32 core_deepest_state = PWRDM_POWER_RET;
+       int next_index = -1;
 
        if (enable_off_mode) {
                mpu_deepest_state = PWRDM_POWER_OFF;
@@ -172,20 +187,20 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
        if ((cx->valid) &&
            (cx->mpu_state >= mpu_deepest_state) &&
            (cx->core_state >= core_deepest_state)) {
-               return curr;
+               return index;
        } else {
                int idx = OMAP3_NUM_STATES - 1;
 
                /* Reach the current state starting at highest C-state */
                for (; idx >= 0; idx--) {
-                       if (&dev->states[idx] == curr) {
-                               next = &dev->states[idx];
+                       if (&drv->states[idx] == curr) {
+                               next_index = idx;
                                break;
                        }
                }
 
                /* Should never hit this condition */
-               WARN_ON(next == NULL);
+               WARN_ON(next_index == -1);
 
                /*
                 * Drop to next valid state.
@@ -193,41 +208,44 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
                 */
                idx--;
                for (; idx >= 0; idx--) {
-                       cx = cpuidle_get_statedata(&dev->states[idx]);
+                       cx = cpuidle_get_statedata(&dev->states_usage[idx]);
                        if ((cx->valid) &&
                            (cx->mpu_state >= mpu_deepest_state) &&
                            (cx->core_state >= core_deepest_state)) {
-                               next = &dev->states[idx];
+                               next_index = idx;
                                break;
                        }
                }
                /*
                 * C1 is always valid.
-                * So, no need to check for 'next==NULL' outside this loop.
+                * So, no need to check for 'next_index == -1' outside
+                * this loop.
                 */
        }
 
-       return next;
+       return next_index;
 }
 
 /**
  * omap3_enter_idle_bm - Checks for any bus activity
  * @dev: cpuidle device
- * @state: The target state to be programmed
+ * @drv: cpuidle driver
+ * @index: array index of target state to be programmed
  *
  * This function checks for any pending activity and then programs
  * the device to the specified or a safer state.
  */
 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
-                              struct cpuidle_state *state)
+                               struct cpuidle_driver *drv,
+                              int index)
 {
-       struct cpuidle_state *new_state;
+       int new_state_idx;
        u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
        struct omap3_idle_statedata *cx;
        int ret;
 
        if (!omap3_can_sleep()) {
-               new_state = dev->safe_state;
+               new_state_idx = drv->safe_state_index;
                goto select_state;
        }
 
@@ -237,7 +255,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
         */
        cam_state = pwrdm_read_pwrst(cam_pd);
        if (cam_state == PWRDM_POWER_ON) {
-               new_state = dev->safe_state;
+               new_state_idx = drv->safe_state_index;
                goto select_state;
        }
 
@@ -253,7 +271,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
         * Prevent PER off if CORE is not in retention or off as this
         * would disable PER wakeups completely.
         */
-       cx = cpuidle_get_statedata(state);
+       cx = cpuidle_get_statedata(&dev->states_usage[index]);
        core_next_state = cx->core_state;
        per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
        if ((per_next_state == PWRDM_POWER_OFF) &&
@@ -264,11 +282,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
        if (per_next_state != per_saved_state)
                pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-       new_state = next_valid_state(dev, state);
+       new_state_idx = next_valid_state(dev, drv, index);
 
 select_state:
-       dev->last_state = new_state;
-       ret = omap3_enter_idle(dev, new_state);
+       ret = omap3_enter_idle(dev, drv, new_state_idx);
 
        /* Restore original PER state if it was modified */
        if (per_next_state != per_saved_state)
@@ -301,22 +318,31 @@ struct cpuidle_driver omap3_idle_driver = {
        .owner =        THIS_MODULE,
 };
 
-/* Helper to fill the C-state common data and register the driver_data */
-static inline struct omap3_idle_statedata *_fill_cstate(
-                                       struct cpuidle_device *dev,
+/* Helper to fill the C-state common data*/
+static inline void _fill_cstate(struct cpuidle_driver *drv,
                                        int idx, const char *descr)
 {
-       struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
-       struct cpuidle_state *state = &dev->states[idx];
+       struct cpuidle_state *state = &drv->states[idx];
 
        state->exit_latency     = cpuidle_params_table[idx].exit_latency;
        state->target_residency = cpuidle_params_table[idx].target_residency;
        state->flags            = CPUIDLE_FLAG_TIME_VALID;
        state->enter            = omap3_enter_idle_bm;
-       cx->valid               = cpuidle_params_table[idx].valid;
        sprintf(state->name, "C%d", idx + 1);
        strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
-       cpuidle_set_statedata(state, cx);
+
+}
+
+/* Helper to register the driver_data */
+static inline struct omap3_idle_statedata *_fill_cstate_usage(
+                                       struct cpuidle_device *dev,
+                                       int idx)
+{
+       struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
+       struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
+
+       cx->valid               = cpuidle_params_table[idx].valid;
+       cpuidle_set_statedata(state_usage, cx);
 
        return cx;
 }
@@ -330,6 +356,7 @@ static inline struct omap3_idle_statedata *_fill_cstate(
 int __init omap3_idle_init(void)
 {
        struct cpuidle_device *dev;
+       struct cpuidle_driver *drv = &omap3_idle_driver;
        struct omap3_idle_statedata *cx;
 
        mpu_pd = pwrdm_lookup("mpu_pwrdm");
@@ -337,44 +364,52 @@ int __init omap3_idle_init(void)
        per_pd = pwrdm_lookup("per_pwrdm");
        cam_pd = pwrdm_lookup("cam_pwrdm");
 
-       cpuidle_register_driver(&omap3_idle_driver);
+
+       drv->safe_state_index = -1;
        dev = &per_cpu(omap3_idle_dev, smp_processor_id());
 
        /* C1 . MPU WFI + Core active */
-       cx = _fill_cstate(dev, 0, "MPU ON + CORE ON");
-       (&dev->states[0])->enter = omap3_enter_idle;
-       dev->safe_state = &dev->states[0];
+       _fill_cstate(drv, 0, "MPU ON + CORE ON");
+       (&drv->states[0])->enter = omap3_enter_idle;
+       drv->safe_state_index = 0;
+       cx = _fill_cstate_usage(dev, 0);
        cx->valid = 1;  /* C1 is always valid */
        cx->mpu_state = PWRDM_POWER_ON;
        cx->core_state = PWRDM_POWER_ON;
 
        /* C2 . MPU WFI + Core inactive */
-       cx = _fill_cstate(dev, 1, "MPU ON + CORE ON");
+       _fill_cstate(drv, 1, "MPU ON + CORE ON");
+       cx = _fill_cstate_usage(dev, 1);
        cx->mpu_state = PWRDM_POWER_ON;
        cx->core_state = PWRDM_POWER_ON;
 
        /* C3 . MPU CSWR + Core inactive */
-       cx = _fill_cstate(dev, 2, "MPU RET + CORE ON");
+       _fill_cstate(drv, 2, "MPU RET + CORE ON");
+       cx = _fill_cstate_usage(dev, 2);
        cx->mpu_state = PWRDM_POWER_RET;
        cx->core_state = PWRDM_POWER_ON;
 
        /* C4 . MPU OFF + Core inactive */
-       cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON");
+       _fill_cstate(drv, 3, "MPU OFF + CORE ON");
+       cx = _fill_cstate_usage(dev, 3);
        cx->mpu_state = PWRDM_POWER_OFF;
        cx->core_state = PWRDM_POWER_ON;
 
        /* C5 . MPU RET + Core RET */
-       cx = _fill_cstate(dev, 4, "MPU RET + CORE RET");
+       _fill_cstate(drv, 4, "MPU RET + CORE RET");
+       cx = _fill_cstate_usage(dev, 4);
        cx->mpu_state = PWRDM_POWER_RET;
        cx->core_state = PWRDM_POWER_RET;
 
        /* C6 . MPU OFF + Core RET */
-       cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET");
+       _fill_cstate(drv, 5, "MPU OFF + CORE RET");
+       cx = _fill_cstate_usage(dev, 5);
        cx->mpu_state = PWRDM_POWER_OFF;
        cx->core_state = PWRDM_POWER_RET;
 
        /* C7 . MPU OFF + Core OFF */
-       cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF");
+       _fill_cstate(drv, 6, "MPU OFF + CORE OFF");
+       cx = _fill_cstate_usage(dev, 6);
        /*
         * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
         * enable OFF mode in a stable form for previous revisions.
@@ -388,6 +423,9 @@ int __init omap3_idle_init(void)
        cx->mpu_state = PWRDM_POWER_OFF;
        cx->core_state = PWRDM_POWER_OFF;
 
+       drv->state_count = OMAP3_NUM_STATES;
+       cpuidle_register_driver(&omap3_idle_driver);
+
        dev->state_count = OMAP3_NUM_STATES;
        if (cpuidle_register_device(dev)) {
                printk(KERN_ERR "%s: CPUidle register device failed\n",
index 68ec03152d5fc4e811842f4cb4c5c6e634a5fae5..c15cfada5f13b5975e36c70331e24032f39e2d66 100644 (file)
@@ -318,18 +318,10 @@ static inline void omap_init_audio(void) {}
 #if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
                defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
 
-static struct omap_device_pm_latency omap_mcpdm_latency[] = {
-       {
-               .deactivate_func = omap_device_idle_hwmods,
-               .activate_func = omap_device_enable_hwmods,
-               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-       },
-};
-
 static void omap_init_mcpdm(void)
 {
        struct omap_hwmod *oh;
-       struct omap_device *od;
+       struct platform_device *pdev;
 
        oh = omap_hwmod_lookup("mcpdm");
        if (!oh) {
@@ -337,11 +329,8 @@ static void omap_init_mcpdm(void)
                return;
        }
 
-       od = omap_device_build("omap-mcpdm", -1, oh, NULL, 0,
-                               omap_mcpdm_latency,
-                               ARRAY_SIZE(omap_mcpdm_latency), 0);
-       if (IS_ERR(od))
-               printk(KERN_ERR "Could not build omap_device for omap-mcpdm-dai\n");
+       pdev = omap_device_build("omap-mcpdm", -1, oh, NULL, 0, NULL, 0, 0);
+       WARN(IS_ERR(pdev), "Can't build omap_device for omap-mcpdm.\n");
 }
 #else
 static inline void omap_init_mcpdm(void) {}
index adb2756e242f104bc8dd35e969ba4957d3407b7a..dce9905d64bb6e1af6c0b80d012142ffdfca49ee 100644 (file)
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 #include <plat/omap-pm.h>
+#include <plat/common.h>
 
 #include "control.h"
+#include "display.h"
+
+#define DISPC_CONTROL          0x0040
+#define DISPC_CONTROL2         0x0238
+#define DISPC_IRQSTATUS                0x0018
+
+#define DSS_SYSCONFIG          0x10
+#define DSS_SYSSTATUS          0x14
+#define DSS_CONTROL            0x40
+#define DSS_SDI_CONTROL                0x44
+#define DSS_PLL_CONTROL                0x48
+
+#define LCD_EN_MASK            (0x1 << 0)
+#define DIGIT_EN_MASK          (0x1 << 1)
+
+#define FRAMEDONE_IRQ_SHIFT    0
+#define EVSYNC_EVEN_IRQ_SHIFT  2
+#define EVSYNC_ODD_IRQ_SHIFT   3
+#define FRAMEDONE2_IRQ_SHIFT   22
+#define FRAMEDONETV_IRQ_SHIFT  24
+
+/*
+ * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC
+ *     reset before deciding that something has gone wrong
+ */
+#define FRAMEDONE_IRQ_TIMEOUT          100
 
 static struct platform_device omap_display_device = {
        .name          = "omapdss",
@@ -172,3 +199,135 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 
        return r;
 }
+
+static void dispc_disable_outputs(void)
+{
+       u32 v, irq_mask = 0;
+       bool lcd_en, digit_en, lcd2_en = false;
+       int i;
+       struct omap_dss_dispc_dev_attr *da;
+       struct omap_hwmod *oh;
+
+       oh = omap_hwmod_lookup("dss_dispc");
+       if (!oh) {
+               WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n");
+               return;
+       }
+
+       if (!oh->dev_attr) {
+               pr_err("display: could not disable outputs during reset due to missing dev_attr\n");
+               return;
+       }
+
+       da = (struct omap_dss_dispc_dev_attr *)oh->dev_attr;
+
+       /* store value of LCDENABLE and DIGITENABLE bits */
+       v = omap_hwmod_read(oh, DISPC_CONTROL);
+       lcd_en = v & LCD_EN_MASK;
+       digit_en = v & DIGIT_EN_MASK;
+
+       /* store value of LCDENABLE for LCD2 */
+       if (da->manager_count > 2) {
+               v = omap_hwmod_read(oh, DISPC_CONTROL2);
+               lcd2_en = v & LCD_EN_MASK;
+       }
+
+       if (!(lcd_en | digit_en | lcd2_en))
+               return; /* no managers currently enabled */
+
+       /*
+        * If any manager was enabled, we need to disable it before
+        * DSS clocks are disabled or DISPC module is reset
+        */
+       if (lcd_en)
+               irq_mask |= 1 << FRAMEDONE_IRQ_SHIFT;
+
+       if (digit_en) {
+               if (da->has_framedonetv_irq) {
+                       irq_mask |= 1 << FRAMEDONETV_IRQ_SHIFT;
+               } else {
+                       irq_mask |= 1 << EVSYNC_EVEN_IRQ_SHIFT |
+                               1 << EVSYNC_ODD_IRQ_SHIFT;
+               }
+       }
+
+       if (lcd2_en)
+               irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
+
+       /*
+        * clear any previous FRAMEDONE, FRAMEDONETV,
+        * EVSYNC_EVEN/ODD or FRAMEDONE2 interrupts
+        */
+       omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);
+
+       /* disable LCD and TV managers */
+       v = omap_hwmod_read(oh, DISPC_CONTROL);
+       v &= ~(LCD_EN_MASK | DIGIT_EN_MASK);
+       omap_hwmod_write(v, oh, DISPC_CONTROL);
+
+       /* disable LCD2 manager */
+       if (da->manager_count > 2) {
+               v = omap_hwmod_read(oh, DISPC_CONTROL2);
+               v &= ~LCD_EN_MASK;
+               omap_hwmod_write(v, oh, DISPC_CONTROL2);
+       }
+
+       i = 0;
+       while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
+              irq_mask) {
+               i++;
+               if (i > FRAMEDONE_IRQ_TIMEOUT) {
+                       pr_err("didn't get FRAMEDONE1/2 or TV interrupt\n");
+                       break;
+               }
+               mdelay(1);
+       }
+}
+
+#define MAX_MODULE_SOFTRESET_WAIT      10000
+int omap_dss_reset(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int c = 0;
+       int i, r;
+
+       if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) {
+               pr_err("dss_core: hwmod data doesn't contain reset data\n");
+               return -EINVAL;
+       }
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk)
+                       clk_enable(oc->_clk);
+
+       dispc_disable_outputs();
+
+       /* clear SDI registers */
+       if (cpu_is_omap3430()) {
+               omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL);
+               omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL);
+       }
+
+       /*
+        * clear DSS_CONTROL register to switch DSS clock sources to
+        * PRCM clock, if any
+        */
+       omap_hwmod_write(0x0, oh, DSS_CONTROL);
+
+       omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
+                               & SYSS_RESETDONE_MASK),
+                       MAX_MODULE_SOFTRESET_WAIT, c);
+
+       if (c == MAX_MODULE_SOFTRESET_WAIT)
+               pr_warning("dss_core: waiting for reset to finish failed\n");
+       else
+               pr_debug("dss_core: softreset done\n");
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk)
+                       clk_disable(oc->_clk);
+
+       r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+
+       return r;
+}
diff --git a/arch/arm/mach-omap2/display.h b/arch/arm/mach-omap2/display.h
new file mode 100644 (file)
index 0000000..b871b01
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * display.h - OMAP2+ integration-specific DSS header
+ *
+ * Copyright (C) 2011 Texas Instruments, 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.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+#define __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+
+#include <linux/kernel.h>
+
+struct omap_dss_dispc_dev_attr {
+       u8      manager_count;
+       bool    has_framedonetv_irq;
+};
+
+#endif
index f77022be783d7fe9d3244fe1df2bf4be94298c6d..fc56745676fa1ea713f8cdc6cff80e5b2b3ac3d5 100644 (file)
@@ -390,7 +390,8 @@ int omap3_noncore_dpll_enable(struct clk *clk)
         * propagating?
         */
        if (!r)
-               clk->rate = omap2_get_dpll_rate(clk);
+               clk->rate = (clk->recalc) ? clk->recalc(clk) :
+                       omap2_get_dpll_rate(clk);
 
        return r;
 }
@@ -424,6 +425,7 @@ void omap3_noncore_dpll_disable(struct clk *clk)
 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 {
        struct clk *new_parent = NULL;
+       unsigned long hw_rate;
        u16 freqsel = 0;
        struct dpll_data *dd;
        int ret;
@@ -435,7 +437,8 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
        if (!dd)
                return -EINVAL;
 
-       if (rate == omap2_get_dpll_rate(clk))
+       hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
+       if (rate == hw_rate)
                return 0;
 
        /*
@@ -455,7 +458,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
                        new_parent = dd->clk_bypass;
        } else {
                if (dd->last_rounded_rate != rate)
-                       omap2_dpll_round_rate(clk, rate);
+                       rate = clk->round_rate(clk, rate);
 
                if (dd->last_rounded_rate == 0)
                        return -EINVAL;
index 4e4da6160d05cdad339ab0fdab9233816e6b84b1..9c6a296b3dc3a0dd6856580b9ddbf5e54ea79e0e 100644 (file)
@@ -19,6 +19,7 @@
 #include <plat/clock.h>
 
 #include "clock.h"
+#include "clock44xx.h"
 #include "cm-regbits-44xx.h"
 
 /* Supported only on OMAP4 */
@@ -82,3 +83,71 @@ const struct clkops clkops_omap4_dpllmx_ops = {
        .deny_idle      = omap4_dpllmx_deny_gatectrl,
 };
 
+/**
+ * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
+ * @clk: struct clk * of the DPLL to compute the rate for
+ *
+ * Compute the output rate for the OMAP4 DPLL represented by @clk.
+ * Takes the REGM4XEN bit into consideration, which is needed for the
+ * OMAP4 ABE DPLL.  Returns the DPLL's output rate (before M-dividers)
+ * upon success, or 0 upon error.
+ */
+unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
+{
+       u32 v;
+       unsigned long rate;
+       struct dpll_data *dd;
+
+       if (!clk || !clk->dpll_data)
+               return 0;
+
+       dd = clk->dpll_data;
+
+       rate = omap2_get_dpll_rate(clk);
+
+       /* regm4xen adds a multiplier of 4 to DPLL calculations */
+       v = __raw_readl(dd->control_reg);
+       if (v & OMAP4430_DPLL_REGM4XEN_MASK)
+               rate *= OMAP4430_REGM4XEN_MULT;
+
+       return rate;
+}
+
+/**
+ * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit
+ * @clk: struct clk * of the DPLL to round a rate for
+ * @target_rate: the desired rate of the DPLL
+ *
+ * Compute the rate that would be programmed into the DPLL hardware
+ * for @clk if set_rate() were to be provided with the rate
+ * @target_rate.  Takes the REGM4XEN bit into consideration, which is
+ * needed for the OMAP4 ABE DPLL.  Returns the rounded rate (before
+ * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
+ * ~0 if an error occurred in omap2_dpll_round_rate().
+ */
+long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
+{
+       u32 v;
+       struct dpll_data *dd;
+       long r;
+
+       if (!clk || !clk->dpll_data)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+
+       /* regm4xen adds a multiplier of 4 to DPLL calculations */
+       v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK;
+
+       if (v)
+               target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
+
+       r = omap2_dpll_round_rate(clk, target_rate);
+       if (r == ~0)
+               return r;
+
+       if (v)
+               clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
+
+       return clk->dpll_data->last_rounded_rate;
+}
index 911cd2e68d46e060291e67a14110e86f17e232f5..74f18f2952df220107c1846e98c4d34b7007243f 100644 (file)
@@ -18,6 +18,7 @@
  * of the OMAP PM core code.
  */
 
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
index 77085847e4e7dafc893a2d255bee5dbac90d4d55..f4a1020559a7b84529f3f6f22e8ffec9ec41c6e3 100644 (file)
@@ -129,15 +129,11 @@ static void omap4_hsmmc1_before_set_reg(struct device *dev, int slot,
         * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
         * card with Vcc regulator (from twl4030 or whatever).  OMAP has both
         * 1.8V and 3.0V modes, controlled by the PBIAS register.
-        *
-        * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
-        * is most naturally TWL VSIM; those pins also use PBIAS.
-        *
-        * FIXME handle VMMC1A as needed ...
         */
        reg = omap4_ctrl_pad_readl(control_pbias_offset);
        reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
-               OMAP4_MMC1_PWRDNZ_MASK);
+               OMAP4_MMC1_PWRDNZ_MASK |
+               OMAP4_MMC1_PBIASLITE_VMODE_MASK);
        omap4_ctrl_pad_writel(reg, control_pbias_offset);
 }
 
@@ -172,12 +168,6 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
                        reg &= ~(OMAP4_MMC1_PWRDNZ_MASK);
                        omap4_ctrl_pad_writel(reg, control_pbias_offset);
                }
-       } else {
-               reg = omap4_ctrl_pad_readl(control_pbias_offset);
-               reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
-                       OMAP4_MMC1_PWRDNZ_MASK |
-                       OMAP4_MMC1_PBIASLITE_VMODE_MASK);
-               omap4_ctrl_pad_writel(reg, control_pbias_offset);
        }
 }
 
@@ -489,7 +479,7 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                        OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
                reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
                        OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
-               reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
+               reg |= (OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK |
                        OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
                        OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
                omap4_ctrl_pad_writel(reg, control_mmc1);
index d27daf921c7ee83d18a82e474c93d3088190d3f3..7f47092a193f71444fee33d01c857f51b8c2c318 100644 (file)
@@ -187,8 +187,11 @@ static void __init omap3_check_features(void)
        OMAP3_CHECK_FEATURE(status, ISP);
        if (cpu_is_omap3630())
                omap_features |= OMAP3_HAS_192MHZ_CLK;
-       if (!cpu_is_omap3505() && !cpu_is_omap3517())
+       if (cpu_is_omap3430() || cpu_is_omap3630())
                omap_features |= OMAP3_HAS_IO_WAKEUP;
+       if (cpu_is_omap3630() || omap_rev() == OMAP3430_REV_ES3_1 ||
+           omap_rev() == OMAP3430_REV_ES3_1_2)
+               omap_features |= OMAP3_HAS_IO_CHAIN_CTRL;
 
        omap_features |= OMAP3_HAS_SDRC;
 
index c88420de1151f9495c0ccf92aa8b718f38218b77..1e2d3322f33eec1e644350c2aeda84718569378a 100644 (file)
 #define OMAP4_DSI2_LANEENABLE_MASK                             (0x7 << 29)
 #define OMAP4_DSI1_LANEENABLE_SHIFT                            24
 #define OMAP4_DSI1_LANEENABLE_MASK                             (0x1f << 24)
-#define OMAP4_DSI1_PIPD_SHIFT                                  19
-#define OMAP4_DSI1_PIPD_MASK                                   (0x1f << 19)
-#define OMAP4_DSI2_PIPD_SHIFT                                  14
-#define OMAP4_DSI2_PIPD_MASK                                   (0x1f << 14)
+#define OMAP4_DSI2_PIPD_SHIFT                                  19
+#define OMAP4_DSI2_PIPD_MASK                                   (0x1f << 19)
+#define OMAP4_DSI1_PIPD_SHIFT                                  14
+#define OMAP4_DSI1_PIPD_MASK                                   (0x1f << 14)
 
 /* CONTROL_MCBSPLP */
 #define OMAP4_ALBCTRLRX_FSX_SHIFT                              31
index a5d8dce2a70b507507221b262d6bc3469bbd06dd..25d20ced03e13cb18bc7d6f27d44d11c5c671d90 100644 (file)
@@ -359,6 +359,7 @@ static void __init omap_hwmod_init_postsetup(void)
        omap_pm_if_early_init();
 }
 
+#ifdef CONFIG_ARCH_OMAP2
 void __init omap2420_init_early(void)
 {
        omap2_set_globals_242x();
@@ -382,11 +383,13 @@ void __init omap2430_init_early(void)
        omap_hwmod_init_postsetup();
        omap2430_clk_init();
 }
+#endif
 
 /*
  * Currently only board-omap3beagle.c should call this because of the
  * same machine_id for 34xx and 36xx beagle.. Will get fixed with DT.
  */
+#ifdef CONFIG_ARCH_OMAP3
 void __init omap3_init_early(void)
 {
        omap2_set_globals_3xxx();
@@ -430,7 +433,9 @@ void __init ti816x_init_early(void)
        omap_hwmod_init_postsetup();
        omap3xxx_clk_init();
 }
+#endif
 
+#ifdef CONFIG_ARCH_OMAP4
 void __init omap4430_init_early(void)
 {
        omap2_set_globals_443x();
@@ -442,6 +447,7 @@ void __init omap4430_init_early(void)
        omap_hwmod_init_postsetup();
        omap4xxx_clk_init();
 }
+#endif
 
 void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
                                      struct omap_sdrc_params *sdrc_cs1)
diff --git a/arch/arm/mach-omap2/io.h b/arch/arm/mach-omap2/io.h
deleted file mode 100644 (file)
index e69de29..0000000
index 86d564a640bb80f8adf1dc961637907592530da4..609ea2ded7e388a22ed9c9d59ba888672ebb13ab 100644 (file)
@@ -10,6 +10,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
index e61feadcda4ee6438b64eb5418871d1733dfebad..b8822048e409c490c949bd8eb4e7329967ac12c9 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/platform_device.h>
 
 #include <plat/iommu.h>
index d713807050807778e33881872413ef354ba33ec7..207a2ff9a8c4e1473c6c497ab8c969f64e0ac0c7 100644 (file)
@@ -749,7 +749,7 @@ static int _count_mpu_irqs(struct omap_hwmod *oh)
                ohii = &oh->mpu_irqs[i++];
        } while (ohii->irq != -1);
 
-       return i;
+       return i-1;
 }
 
 /**
@@ -772,7 +772,7 @@ static int _count_sdma_reqs(struct omap_hwmod *oh)
                ohdi = &oh->sdma_reqs[i++];
        } while (ohdi->dma_req != -1);
 
-       return i;
+       return i-1;
 }
 
 /**
@@ -795,7 +795,7 @@ static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os)
                mem = &os->addr[i++];
        } while (mem->pa_start != mem->pa_end);
 
-       return i;
+       return i-1;
 }
 
 /**
@@ -2625,7 +2625,7 @@ ohsps_unlock:
  * Returns the context loss count of the powerdomain assocated with @oh
  * upon success, or zero if no powerdomain exists for @oh.
  */
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 {
        struct powerdomain *pwrdm;
        int ret = 0;
index 6d7206213525d03ac830d8ca6092ce4317863f37..a5409ce3f3233eaac531ed070fc1f9cf74e8398f 100644 (file)
@@ -875,6 +875,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+       /*
+        * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+        * driver does not use these clocks.
+        */
        { .role = "tv_clk", .clk = "dss_54m_fck" },
        { .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -899,7 +903,7 @@ static struct omap_hwmod omap2420_dss_core_hwmod = {
        .slaves_cnt     = ARRAY_SIZE(omap2420_dss_slaves),
        .masters        = omap2420_dss_masters,
        .masters_cnt    = ARRAY_SIZE(omap2420_dss_masters),
-       .flags          = HWMOD_NO_IDLEST,
+       .flags          = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 /* l4_core -> dss_dispc */
@@ -939,6 +943,7 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
        .slaves         = omap2420_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_dss_dispc_slaves),
        .flags          = HWMOD_NO_IDLEST,
+       .dev_attr       = &omap2_3_dss_dispc_dev_attr
 };
 
 /* l4_core -> dss_rfbi */
@@ -961,6 +966,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
        &omap2420_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+       { .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
        .name           = "dss_rfbi",
        .class          = &omap2_rfbi_hwmod_class,
@@ -972,6 +981,8 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
                        .module_offs = CORE_MOD,
                },
        },
+       .opt_clks       = dss_rfbi_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
        .slaves         = omap2420_dss_rfbi_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_dss_rfbi_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -981,7 +992,7 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
        .master         = &omap2420_l4_core_hwmod,
        .slave          = &omap2420_dss_venc_hwmod,
-       .clk            = "dss_54m_fck",
+       .clk            = "dss_ick",
        .addr           = omap2_dss_venc_addrs,
        .fw = {
                .omap2 = {
@@ -1001,7 +1012,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
 static struct omap_hwmod omap2420_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap2_venc_hwmod_class,
-       .main_clk       = "dss1_fck",
+       .main_clk       = "dss_54m_fck",
        .prcm           = {
                .omap2 = {
                        .prcm_reg_id = 1,
index a2580d01c3ff98b25a57b6508bd959d0e58c700f..c4f56cb60d7d676ddda36e232c8b385a58fef6ba 100644 (file)
@@ -942,6 +942,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+       /*
+        * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+        * driver does not use these clocks.
+        */
        { .role = "tv_clk", .clk = "dss_54m_fck" },
        { .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -966,7 +970,7 @@ static struct omap_hwmod omap2430_dss_core_hwmod = {
        .slaves_cnt     = ARRAY_SIZE(omap2430_dss_slaves),
        .masters        = omap2430_dss_masters,
        .masters_cnt    = ARRAY_SIZE(omap2430_dss_masters),
-       .flags          = HWMOD_NO_IDLEST,
+       .flags          = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 /* l4_core -> dss_dispc */
@@ -1000,6 +1004,7 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
        .slaves         = omap2430_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_dss_dispc_slaves),
        .flags          = HWMOD_NO_IDLEST,
+       .dev_attr       = &omap2_3_dss_dispc_dev_attr
 };
 
 /* l4_core -> dss_rfbi */
@@ -1016,6 +1021,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
        &omap2430_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+       { .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
        .name           = "dss_rfbi",
        .class          = &omap2_rfbi_hwmod_class,
@@ -1027,6 +1036,8 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
                        .module_offs = CORE_MOD,
                },
        },
+       .opt_clks       = dss_rfbi_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
        .slaves         = omap2430_dss_rfbi_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_dss_rfbi_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -1036,7 +1047,7 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
        .master         = &omap2430_l4_core_hwmod,
        .slave          = &omap2430_dss_venc_hwmod,
-       .clk            = "dss_54m_fck",
+       .clk            = "dss_ick",
        .addr           = omap2_dss_venc_addrs,
        .flags          = OCPIF_SWSUP_IDLE,
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
@@ -1050,7 +1061,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
 static struct omap_hwmod omap2430_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap2_venc_hwmod_class,
-       .main_clk       = "dss1_fck",
+       .main_clk       = "dss_54m_fck",
        .prcm           = {
                .omap2 = {
                        .prcm_reg_id = 1,
index c451729d289adfd17090c3be58c53937626835fe..c11273da5dcc33f046e94babfdb6f34c1d6f2778 100644 (file)
@@ -11,6 +11,7 @@
 #include <plat/omap_hwmod.h>
 #include <plat/serial.h>
 #include <plat/dma.h>
+#include <plat/common.h>
 
 #include <mach/irqs.h>
 
@@ -43,13 +44,15 @@ static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
        .syss_offs      = 0x0014,
-       .sysc_flags     = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .sysc_flags     = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+                          SYSS_HAS_RESET_STATUS),
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
 struct omap_hwmod_class omap2_dss_hwmod_class = {
        .name   = "dss",
        .sysc   = &omap2_dss_sysc,
+       .reset  = omap_dss_reset,
 };
 
 /*
index 3008e1672c7a051e54e84ed2e147ea2674e019e4..7f8915ad50990b1af2e877ed169c32cd0d15cd02 100644 (file)
@@ -1369,9 +1369,14 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
-       { .role = "tv_clk", .clk = "dss_tv_fck" },
-       { .role = "video_clk", .clk = "dss_96m_fck" },
+       /*
+        * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+        * driver does not use these clocks.
+        */
        { .role = "sys_clk", .clk = "dss2_alwon_fck" },
+       { .role = "tv_clk", .clk = "dss_tv_fck" },
+       /* required only on OMAP3430 */
+       { .role = "tv_dac_clk", .clk = "dss_96m_fck" },
 };
 
 static struct omap_hwmod omap3430es1_dss_core_hwmod = {
@@ -1394,11 +1399,12 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
        .slaves_cnt     = ARRAY_SIZE(omap3430es1_dss_slaves),
        .masters        = omap3xxx_dss_masters,
        .masters_cnt    = ARRAY_SIZE(omap3xxx_dss_masters),
-       .flags          = HWMOD_NO_IDLEST,
+       .flags          = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 static struct omap_hwmod omap3xxx_dss_core_hwmod = {
        .name           = "dss_core",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .class          = &omap2_dss_hwmod_class,
        .main_clk       = "dss1_alwon_fck", /* instead of dss_fck */
        .sdma_reqs      = omap3xxx_dss_sdma_chs,
@@ -1456,6 +1462,7 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
        .slaves         = omap3xxx_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
        .flags          = HWMOD_NO_IDLEST,
+       .dev_attr       = &omap2_3_dss_dispc_dev_attr
 };
 
 /*
@@ -1486,6 +1493,7 @@ static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &omap3xxx_dss_dsi1_hwmod,
+       .clk            = "dss_ick",
        .addr           = omap3xxx_dss_dsi1_addrs,
        .fw = {
                .omap2 = {
@@ -1502,6 +1510,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
        &omap3xxx_l4_core__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
+       { .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
        .name           = "dss_dsi1",
        .class          = &omap3xxx_dsi_hwmod_class,
@@ -1514,6 +1526,8 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
                        .module_offs = OMAP3430_DSS_MOD,
                },
        },
+       .opt_clks       = dss_dsi1_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_dsi1_opt_clks),
        .slaves         = omap3xxx_dss_dsi1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -1540,6 +1554,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
        &omap3xxx_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+       { .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
        .name           = "dss_rfbi",
        .class          = &omap2_rfbi_hwmod_class,
@@ -1551,6 +1569,8 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
                        .module_offs = OMAP3430_DSS_MOD,
                },
        },
+       .opt_clks       = dss_rfbi_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
        .slaves         = omap3xxx_dss_rfbi_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -1560,7 +1580,7 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &omap3xxx_dss_venc_hwmod,
-       .clk            = "dss_tv_fck",
+       .clk            = "dss_ick",
        .addr           = omap2_dss_venc_addrs,
        .fw = {
                .omap2 = {
@@ -1578,10 +1598,15 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
        &omap3xxx_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = {
+       /* required only on OMAP3430 */
+       { .role = "tv_dac_clk", .clk = "dss_96m_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap2_venc_hwmod_class,
-       .main_clk       = "dss1_alwon_fck",
+       .main_clk       = "dss_tv_fck",
        .prcm           = {
                .omap2 = {
                        .prcm_reg_id = 1,
@@ -1589,6 +1614,8 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
                        .module_offs = OMAP3430_DSS_MOD,
                },
        },
+       .opt_clks       = dss_venc_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_venc_opt_clks),
        .slaves         = omap3xxx_dss_venc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_dss_venc_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -3159,7 +3186,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_mmc2_hwmod,
        &omap3xxx_mmc3_hwmod,
        &omap3xxx_mpu_hwmod,
-       &omap3xxx_iva_hwmod,
 
        &omap3xxx_timer1_hwmod,
        &omap3xxx_timer2_hwmod,
@@ -3188,8 +3214,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_i2c1_hwmod,
        &omap3xxx_i2c2_hwmod,
        &omap3xxx_i2c3_hwmod,
-       &omap34xx_sr1_hwmod,
-       &omap34xx_sr2_hwmod,
 
        /* gpio class */
        &omap3xxx_gpio1_hwmod,
@@ -3211,8 +3235,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_mcbsp2_sidetone_hwmod,
        &omap3xxx_mcbsp3_sidetone_hwmod,
 
-       /* mailbox class */
-       &omap3xxx_mailbox_hwmod,
 
        /* mcspi class */
        &omap34xx_mcspi1,
@@ -3225,31 +3247,39 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 
 /* 3430ES1-only hwmods */
 static __initdata struct omap_hwmod *omap3430es1_hwmods[] = {
+       &omap3xxx_iva_hwmod,
        &omap3430es1_dss_core_hwmod,
+       &omap3xxx_mailbox_hwmod,
        NULL
 };
 
 /* 3430ES2+-only hwmods */
 static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = {
+       &omap3xxx_iva_hwmod,
        &omap3xxx_dss_core_hwmod,
        &omap3xxx_usbhsotg_hwmod,
+       &omap3xxx_mailbox_hwmod,
        NULL
 };
 
 /* 34xx-only hwmods (all ES revisions) */
 static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
+       &omap3xxx_iva_hwmod,
        &omap34xx_sr1_hwmod,
        &omap34xx_sr2_hwmod,
+       &omap3xxx_mailbox_hwmod,
        NULL
 };
 
 /* 36xx-only hwmods (all ES revisions) */
 static __initdata struct omap_hwmod *omap36xx_hwmods[] = {
+       &omap3xxx_iva_hwmod,
        &omap3xxx_uart4_hwmod,
        &omap3xxx_dss_core_hwmod,
        &omap36xx_sr1_hwmod,
        &omap36xx_sr2_hwmod,
        &omap3xxx_usbhsotg_hwmod,
+       &omap3xxx_mailbox_hwmod,
        NULL
 };
 
@@ -3267,7 +3297,7 @@ int __init omap3xxx_hwmod_init(void)
 
        /* Register hwmods common to all OMAP3 */
        r = omap_hwmod_register(omap3xxx_hwmods);
-       if (!r)
+       if (r < 0)
                return r;
 
        rev = omap_rev();
@@ -3292,7 +3322,7 @@ int __init omap3xxx_hwmod_init(void)
        };
 
        r = omap_hwmod_register(h);
-       if (!r)
+       if (r < 0)
                return r;
 
        /*
index 7695e5d43316686429158ec56aafacbc7d25a6a7..daaf165af696f212c6dcadb4db7ac3539d54dcd6 100644 (file)
@@ -30,6 +30,7 @@
 #include <plat/mmc.h>
 #include <plat/i2c.h>
 #include <plat/dmtimer.h>
+#include <plat/common.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -1187,6 +1188,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = {
 static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
        .name   = "dss",
        .sysc   = &omap44xx_dss_sysc,
+       .reset  = omap_dss_reset,
 };
 
 /* dss */
@@ -1240,12 +1242,12 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = {
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
        { .role = "sys_clk", .clk = "dss_sys_clk" },
        { .role = "tv_clk", .clk = "dss_tv_clk" },
-       { .role = "dss_clk", .clk = "dss_dss_clk" },
-       { .role = "video_clk", .clk = "dss_48mhz_clk" },
+       { .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
 };
 
 static struct omap_hwmod omap44xx_dss_hwmod = {
        .name           = "dss_core",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .class          = &omap44xx_dss_hwmod_class,
        .clkdm_name     = "l3_dss_clkdm",
        .main_clk       = "dss_dss_clk",
@@ -1325,6 +1327,11 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = {
        { }
 };
 
+static struct omap_dss_dispc_dev_attr omap44xx_dss_dispc_dev_attr = {
+       .manager_count          = 3,
+       .has_framedonetv_irq    = 1
+};
+
 /* l4_per -> dss_dispc */
 static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
        .master         = &omap44xx_l4_per_hwmod,
@@ -1340,12 +1347,6 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
        &omap44xx_l4_per__dss_dispc,
 };
 
-static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = {
-       { .role = "sys_clk", .clk = "dss_sys_clk" },
-       { .role = "tv_clk", .clk = "dss_tv_clk" },
-       { .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
-};
-
 static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
        .name           = "dss_dispc",
        .class          = &omap44xx_dispc_hwmod_class,
@@ -1359,10 +1360,9 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
                        .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
-       .opt_clks       = dss_dispc_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(dss_dispc_opt_clks),
        .slaves         = omap44xx_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_dss_dispc_slaves),
+       .dev_attr       = &omap44xx_dss_dispc_dev_attr
 };
 
 /*
@@ -1624,7 +1624,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
        .clkdm_name     = "l3_dss_clkdm",
        .mpu_irqs       = omap44xx_dss_hdmi_irqs,
        .sdma_reqs      = omap44xx_dss_hdmi_sdma_reqs,
-       .main_clk       = "dss_dss_clk",
+       .main_clk       = "dss_48mhz_clk",
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
@@ -1785,7 +1785,7 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap44xx_venc_hwmod_class,
        .clkdm_name     = "l3_dss_clkdm",
-       .main_clk       = "dss_dss_clk",
+       .main_clk       = "dss_tv_clk",
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
index de832ebc93a98c8d2556675de6ae3bfd7a5b2342..51e5418899fb446cd2317efe2622e3683860eec4 100644 (file)
@@ -49,3 +49,7 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = {
        .srst_shift     = SYSC_TYPE2_SOFTRESET_SHIFT,
 };
 
+struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = {
+       .manager_count          = 2,
+       .has_framedonetv_irq    = 0
+};
index 39a7c37f45870446a9f61d682eb5cc333cbac94c..ad5d8f04c0b8803edeac09dff53686c156365b91 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <plat/omap_hwmod.h>
 
+#include "display.h"
+
 /* Common address space across OMAP2xxx */
 extern struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[];
 extern struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[];
@@ -111,4 +113,6 @@ extern struct omap_hwmod_class omap2xxx_dma_hwmod_class;
 extern struct omap_hwmod_class omap2xxx_mailbox_hwmod_class;
 extern struct omap_hwmod_class omap2xxx_mcspi_class;
 
+extern struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr;
+
 #endif
index c8b1bef92e5ad372cf02699bed78a302da236dc4..d15225ff5c4969b3ddde9cc79ece7caf725001eb 100644 (file)
@@ -20,6 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  * USA
  */
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
@@ -236,7 +237,7 @@ static int __devexit omap4_l3_remove(struct platform_device *pdev)
 static const struct of_device_id l3_noc_match[] = {
        {.compatible = "ti,omap4-l3-noc", },
        {},
-}
+};
 MODULE_DEVICE_TABLE(of, l3_noc_match);
 #else
 #define l3_noc_match NULL
index 1e79bdf313e311fc945fb56bb2dffa3817d3b86e..00bff46ca48beb606557f8fba7a1974f571ebb91 100644 (file)
@@ -24,6 +24,7 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "pm.h"
+#include "twl-common.h"
 
 static struct omap_device_pm_latency *pm_lats;
 
@@ -226,11 +227,8 @@ postcore_initcall(omap2_common_pm_init);
 
 static int __init omap2_common_pm_late_init(void)
 {
-       /* Init the OMAP TWL parameters */
-       omap3_twl_init();
-       omap4_twl_init();
-
        /* Init the voltage layer */
+       omap_pmic_late_init();
        omap_voltage_late_init();
 
        /* Initialize the voltages */
index c8cbd00a41af9cf6da518a67f9bff37784ebcbd3..efa66494c1e3c82ff6e1adfee5ef812d57e13089 100644 (file)
@@ -99,31 +99,27 @@ static void omap3_enable_io_chain(void)
 {
        int timeout = 0;
 
-       if (omap_rev() >= OMAP3430_REV_ES3_1) {
-               omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-                                    PM_WKEN);
-               /* Do a readback to assure write has been done */
-               omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
-
-               while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
-                        OMAP3430_ST_IO_CHAIN_MASK)) {
-                       timeout++;
-                       if (timeout > 1000) {
-                               printk(KERN_ERR "Wake up daisy chain "
-                                      "activation failed.\n");
-                               return;
-                       }
-                       omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-                                            WKUP_MOD, PM_WKEN);
+       omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+                                  PM_WKEN);
+       /* Do a readback to assure write has been done */
+       omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+
+       while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
+                OMAP3430_ST_IO_CHAIN_MASK)) {
+               timeout++;
+               if (timeout > 1000) {
+                       pr_err("Wake up daisy chain activation failed.\n");
+                       return;
                }
+               omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
+                                          WKUP_MOD, PM_WKEN);
        }
 }
 
 static void omap3_disable_io_chain(void)
 {
-       if (omap_rev() >= OMAP3430_REV_ES3_1)
-               omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-                                      PM_WKEN);
+       omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+                                    PM_WKEN);
 }
 
 static void omap3_core_save_context(void)
@@ -363,7 +359,6 @@ void omap_sram_idle(void)
                printk(KERN_ERR "Invalid mpu state in sram_idle\n");
                return;
        }
-       pwrdm_pre_transition();
 
        /* NEON control */
        if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
@@ -376,7 +371,8 @@ void omap_sram_idle(void)
            (per_next_state < PWRDM_POWER_ON ||
             core_next_state < PWRDM_POWER_ON)) {
                omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
-               omap3_enable_io_chain();
+               if (omap3_has_io_chain_ctrl())
+                       omap3_enable_io_chain();
        }
 
        /* Block console output in case it is on one of the OMAP UARTs */
@@ -386,6 +382,8 @@ void omap_sram_idle(void)
                        if (!console_trylock())
                                goto console_still_active;
 
+       pwrdm_pre_transition();
+
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
                per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
@@ -409,13 +407,14 @@ void omap_sram_idle(void)
        omap3_intc_prepare_idle();
 
        /*
-       * On EMU/HS devices ROM code restores a SRDC value
-       * from scratchpad which has automatic self refresh on timeout
-       * of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
-       * Hence store/restore the SDRC_POWER register here.
-       */
-       if (omap_rev() >= OMAP3430_REV_ES3_0 &&
-           omap_type() != OMAP2_DEVICE_TYPE_GP &&
+        * On EMU/HS devices ROM code restores a SRDC value
+        * from scratchpad which has automatic self refresh on timeout
+        * of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
+        * Hence store/restore the SDRC_POWER register here.
+        */
+       if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
+           (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
+            omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
            core_next_state == PWRDM_POWER_OFF)
                sdrc_pwr = sdrc_read_reg(SDRC_POWER);
 
@@ -432,8 +431,9 @@ void omap_sram_idle(void)
                omap34xx_do_sram_idle(save_state);
 
        /* Restore normal SDRC POWER settings */
-       if (omap_rev() >= OMAP3430_REV_ES3_0 &&
-           omap_type() != OMAP2_DEVICE_TYPE_GP &&
+       if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
+           (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
+            omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
            core_next_state == PWRDM_POWER_OFF)
                sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
@@ -455,6 +455,8 @@ void omap_sram_idle(void)
        }
        omap3_intc_resume_idle();
 
+       pwrdm_post_transition();
+
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
                per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
@@ -475,11 +477,10 @@ console_still_active:
             core_next_state < PWRDM_POWER_ON)) {
                omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
                                             PM_WKEN);
-               omap3_disable_io_chain();
+               if (omap3_has_io_chain_ctrl())
+                       omap3_disable_io_chain();
        }
 
-       pwrdm_post_transition();
-
        clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
@@ -870,6 +871,9 @@ static int __init omap3_pm_init(void)
        if (!cpu_is_omap34xx())
                return -ENODEV;
 
+       if (!omap3_has_io_chain_ctrl())
+               pr_warning("PM: no software I/O chain control; some wakeups may be lost\n");
+
        pm_errata_configure();
 
        /* XXX prcm_setup_regs needs to be before enabling hw
index 5164d587ef52a17fa5083c71506ed801ce9dd382..8a18d1bd61c80af893e3cc549daaaa2e10b90db3 100644 (file)
@@ -1002,16 +1002,16 @@ int pwrdm_post_transition(void)
  * @pwrdm: struct powerdomain * to wait for
  *
  * Context loss count is the sum of powerdomain off-mode counter, the
- * logic off counter and the per-bank memory off counter.  Returns 0
+ * logic off counter and the per-bank memory off counter.  Returns negative
  * (and WARNs) upon error, otherwise, returns the context loss count.
  */
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 {
        int i, count;
 
        if (!pwrdm) {
                WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
-               return 0;
+               return -ENODEV;
        }
 
        count = pwrdm->state_counter[PWRDM_POWER_OFF];
@@ -1020,7 +1020,13 @@ u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
        for (i = 0; i < pwrdm->banks; i++)
                count += pwrdm->ret_mem_off_counter[i];
 
-       pr_debug("powerdomain: %s: context loss count = %u\n",
+       /*
+        * Context loss count has to be a non-negative value. Clear the sign
+        * bit to get a value range from 0 to INT_MAX.
+        */
+       count &= INT_MAX;
+
+       pr_debug("powerdomain: %s: context loss count = %d\n",
                 pwrdm->name, count);
 
        return count;
index 42e6dd8f2a78dd37521f06780cc76bb5050b01de..0d72a8a8ce4d36a00ce23fcfbe297d6087854c0f 100644 (file)
@@ -217,7 +217,7 @@ int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
 extern void omap242x_powerdomains_init(void);
index 0347b93211e6d468257f3a0bd365ebb28726edd8..cf246b39bac745dc315576ecc161c35666643381 100644 (file)
@@ -17,6 +17,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -138,7 +139,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
                sr_write_reg(sr_info, ERRCONFIG_V1, status);
        } else if (sr_info->ip_type == SR_TYPE_V2) {
                /* Read the status bits */
-               sr_read_reg(sr_info, IRQSTATUS);
+               status = sr_read_reg(sr_info, IRQSTATUS);
 
                /* Clear them by writing back */
                sr_write_reg(sr_info, IRQSTATUS, status);
index e49fc7be2229badcd274038b7a308ce6def8c478..037b0d7d4e05b1b77f0d93035283484ce3ba1078 100644 (file)
@@ -408,14 +408,6 @@ static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
        return ret;
 }
 
-struct omap_device_pm_latency omap2_dmtimer_latency[] = {
-       {
-               .deactivate_func = omap_device_idle_hwmods,
-               .activate_func   = omap_device_enable_hwmods,
-               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-       },
-};
-
 /**
  * omap_timer_init - build and register timer device with an
  * associated timer hwmod
@@ -477,9 +469,7 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
        pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
 #endif
        pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
-                       omap2_dmtimer_latency,
-                       ARRAY_SIZE(omap2_dmtimer_latency),
-                       0);
+                                NULL, 0, 0);
 
        if (IS_ERR(pdev)) {
                pr_err("%s: Can't build omap_device for %s: %s.\n",
index 5224357721686dc41d5a703a3ba02ae1e1e7bf6a..10b20c652e5dc390026bc1eec5042ff351c387f4 100644 (file)
@@ -30,6 +30,7 @@
 #include <plat/usb.h>
 
 #include "twl-common.h"
+#include "pm.h"
 
 static struct i2c_board_info __initdata pmic_i2c_board_info = {
        .addr           = 0x48,
@@ -48,6 +49,16 @@ void __init omap_pmic_init(int bus, u32 clkrate,
        omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
 }
 
+void __init omap_pmic_late_init(void)
+{
+       /* Init the OMAP TWL parameters (if PMIC has been registerd) */
+       if (!pmic_i2c_board_info.irq)
+               return;
+
+       omap3_twl_init();
+       omap4_twl_init();
+}
+
 #if defined(CONFIG_ARCH_OMAP3)
 static struct twl4030_usb_data omap3_usb_pdata = {
        .usb_mode       = T2_USB_MODE_ULPI,
index 5e83a5bd37fb719dd06ea8deac01e0c3c2922e80..275dde8cb27aa789ce4d9bfa89c8ed92fb122711 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __OMAP_PMIC_COMMON__
 #define __OMAP_PMIC_COMMON__
 
+#include <plat/irqs.h>
+
 #define TWL_COMMON_PDATA_USB           (1 << 0)
 #define TWL_COMMON_PDATA_BCI           (1 << 1)
 #define TWL_COMMON_PDATA_MADC          (1 << 2)
@@ -30,6 +32,7 @@ struct twl4030_platform_data;
 
 void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
                    struct twl4030_platform_data *pmic_data);
+void omap_pmic_late_init(void);
 
 static inline void omap2_pmic_init(const char *pmic_type,
                                   struct twl4030_platform_data *pmic_data)
index 47fb5d607630678e6ce076ef9e311f3cdbb309b6..267975086a7b5b04a14fe2184c3ed02678f67ea4 100644 (file)
@@ -60,44 +60,6 @@ static struct musb_hdrc_platform_data musb_plat = {
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
-static void usb_musb_mux_init(struct omap_musb_board_data *board_data)
-{
-       switch (board_data->interface_type) {
-       case MUSB_INTERFACE_UTMI:
-               omap_mux_init_signal("usba0_otg_dp", OMAP_PIN_INPUT);
-               omap_mux_init_signal("usba0_otg_dm", OMAP_PIN_INPUT);
-               break;
-       case MUSB_INTERFACE_ULPI:
-               omap_mux_init_signal("usba0_ulpiphy_clk",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_stp",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dir",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_nxt",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dat0",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dat1",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dat2",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dat3",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dat4",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dat5",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dat6",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               omap_mux_init_signal("usba0_ulpiphy_dat7",
-                                               OMAP_PIN_INPUT_PULLDOWN);
-               break;
-       default:
-               break;
-       }
-}
-
 static struct omap_musb_board_data musb_default_board_data = {
        .interface_type         = MUSB_INTERFACE_ULPI,
        .mode                   = MUSB_OTG,
index 6c75cd35c4c836b5700c367c346db1b1f0c79bc7..b35e2005a348e6fbc4c960d83e0d2d0d75cf889f 100644 (file)
@@ -275,7 +275,7 @@ static struct platform_nand_data ts78xx_ts_nand_data = {
                .partitions             = ts78xx_ts_nand_parts,
                .nr_partitions          = ARRAY_SIZE(ts78xx_ts_nand_parts),
                .chip_delay             = 15,
-               .options                = NAND_USE_FLASH_BBT,
+               .bbt_options            = NAND_BBT_USE_FLASH,
        },
        .ctrl   = {
                /*
index 8f2c234ed9d9bd7a59767562f896a9ec85005349..58d4ee3ae9499d062cd68e972596dbc6f0ffc521 100644 (file)
@@ -14,7 +14,7 @@
 
 #define UART_SHIFT 2
 
-               .macro  addruart, rp, rv
+               .macro  addruart, rp, rv, tmp
                ldr     \rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
                ldr     \rp, =PICOXCELL_UART1_BASE
                .endm
index 1c7890cdb0c907837eb9121655030ab900c0135c..11f2223da5765c942312b80d9bee244dea3353b3 100644 (file)
@@ -307,7 +307,7 @@ static inline void balloon3_mmc_init(void) {}
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static void balloon3_udc_command(int cmd)
 {
        if (cmd == PXA2XX_UDC_CMD_CONNECT)
index 21ac8e3e2f7a191cd58748f759c19030fa009f84..684acf6ed3d5c1b0d370c12c8eedee166da84a5e 100644 (file)
@@ -424,8 +424,9 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
        .enable_arbiter = 1,
        .keep_config    = 1,
-       .parts          = cm_x300_nand_partitions,
-       .nr_parts       = ARRAY_SIZE(cm_x300_nand_partitions),
+       .num_cs         = 1,
+       .parts[0]       = cm_x300_nand_partitions,
+       .nr_parts[0]    = ARRAY_SIZE(cm_x300_nand_partitions),
 };
 
 static void __init cm_x300_init_nand(void)
index 8cbb2b43ed1118533761dbaede778d85d6da2552..56ab7a634bcac80ebe1e1511b086d7e04027da59 100644 (file)
@@ -146,7 +146,7 @@ static void __init colibri_pxa320_init_eth(void)
 static inline void __init colibri_pxa320_init_eth(void) {}
 #endif /* CONFIG_AX88796 */
 
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info colibri_pxa320_gpio_vbus_info = {
        .gpio_vbus              = mfp_to_gpio(MFP_PIN_GPIO96),
        .gpio_pullup            = -1,
index 3f9be419959da6356025a2b23a385a9e40db6ec7..2b8ca0de8a3d7369b4c133ad6c29796f2ca85d7e 100644 (file)
@@ -139,8 +139,9 @@ static struct mtd_partition colibri_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data colibri_nand_info = {
        .enable_arbiter = 1,
        .keep_config    = 1,
-       .parts          = colibri_nand_partitions,
-       .nr_parts       = ARRAY_SIZE(colibri_nand_partitions),
+       .num_cs         = 1,
+       .parts[0]       = colibri_nand_partitions,
+       .nr_parts[0]    = ARRAY_SIZE(colibri_nand_partitions),
 };
 
 void __init colibri_pxa3xx_init_nand(void)
index 9c8208ca04150e4a3bbb2d41cccb28287a0efe99..ffdd70dad327dd135f1a2d5fc36a3cde45f2f86b 100644 (file)
@@ -106,7 +106,7 @@ static void __init gumstix_mmc_init(void)
 }
 #endif
 
-#ifdef CONFIG_USB_GADGET_PXA25X
+#ifdef CONFIG_USB_PXA25X
 static struct gpio_vbus_mach_info gumstix_udc_info = {
        .gpio_vbus              = GPIO_GUMSTIX_USB_GPIOn,
        .gpio_pullup            = GPIO_GUMSTIX_USB_GPIOx,
index f80bbe246afe5812b17db200d709b13f6160f72c..d4eac3d6ffb5ecd04df4abeb0ed45b32a2882705 100644 (file)
@@ -37,8 +37,8 @@ extern void __init palm27x_lcd_init(int power,
 #define palm27x_lcd_init(power, mode)  do {} while (0)
 #endif
 
-#if    defined(CONFIG_USB_GADGET_PXA27X) || \
-       defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if    defined(CONFIG_USB_PXA27X) || \
+       defined(CONFIG_USB_PXA27X_MODULE)
 extern void __init palm27x_udc_init(int vbus, int pullup,
                                        int vbus_inverted);
 #else
index 27147f6ff7cb49965c7bae0c14deed4801b6a31b..d21e28b46d81032c2d4dd733f09418c89f2c1267 100644 (file)
@@ -325,8 +325,9 @@ static struct mtd_partition littleton_nand_partitions[] = {
 
 static struct pxa3xx_nand_platform_data littleton_nand_info = {
        .enable_arbiter = 1,
-       .parts          = littleton_nand_partitions,
-       .nr_parts       = ARRAY_SIZE(littleton_nand_partitions),
+       .num_cs         = 1,
+       .parts[0]       = littleton_nand_partitions,
+       .nr_parts[0]    = ARRAY_SIZE(littleton_nand_partitions),
 };
 
 static void __init littleton_init_nand(void)
index a13a1e3658518ef1bb7fdf737031bc9c409d2627..83570a79e7d24f02e8f9bd0db1bc6247bf8cbeee 100644 (file)
@@ -389,10 +389,11 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = {
 };
 
 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
-       .enable_arbiter = 1,
-       .keep_config = 1,
-       .parts = mxm_8x10_nand_partitions,
-       .nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions)
+       .enable_arbiter = 1,
+       .keep_config    = 1,
+       .num_cs         = 1,
+       .parts[0]       = mxm_8x10_nand_partitions,
+       .nr_parts[0]    = ARRAY_SIZE(mxm_8x10_nand_partitions)
 };
 
 static void __init mxm_8x10_nand_init(void)
index 325c245c0a0dd3916129b2875caaec931758137e..fbc10d7b95d1e8ef7ceec5dd03d512c7c2d314bf 100644 (file)
@@ -164,8 +164,8 @@ void __init palm27x_lcd_init(int power, struct pxafb_mode_info *mode)
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if    defined(CONFIG_USB_GADGET_PXA27X) || \
-       defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if    defined(CONFIG_USB_PXA27X) || \
+       defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info palm27x_udc_info = {
        .gpio_vbus_inverted     = 1,
 };
index 6ec7caefb37c8219d02f45fc0088249295006fa5..2c24c67fd92b6d863fc2e534b6ad9f15b7daaaf7 100644 (file)
@@ -338,7 +338,7 @@ static inline void palmtc_mkp_init(void) {}
 /******************************************************************************
  * UDC
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA25X)||defined(CONFIG_USB_GADGET_PXA25X_MODULE)
+#if defined(CONFIG_USB_PXA25X)||defined(CONFIG_USB_PXA25X_MODULE)
 static struct gpio_vbus_mach_info palmtc_udc_info = {
        .gpio_vbus              = GPIO_NR_PALMTC_USB_DETECT_N,
        .gpio_vbus_inverted     = 1,
index 9c58e87f2b82d274087d0180dc5cc8bb04ff55f7..78d643783f990aa7560170502f35e4ad857dc91c 100644 (file)
@@ -346,8 +346,9 @@ static struct mtd_partition raumfeld_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
        .enable_arbiter = 1,
        .keep_config    = 1,
-       .parts          = raumfeld_nand_partitions,
-       .nr_parts       = ARRAY_SIZE(raumfeld_nand_partitions),
+       .num_cs         = 1,
+       .parts[0]       = raumfeld_nand_partitions,
+       .nr_parts[0]    = ARRAY_SIZE(raumfeld_nand_partitions),
 };
 
 /**
index bf2403c424bf5d7949f624bb9a635a928b6fc99e..9edeec65f6a3b640b4860e38e9387f4f4892aeb3 100644 (file)
@@ -343,7 +343,7 @@ static inline void vpac270_uhc_init(void) {}
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info vpac270_gpio_vbus_info = {
        .gpio_vbus              = GPIO41_VPAC270_UDC_DETECT,
        .gpio_pullup            = -1,
index 2406fd2727efc526fda5eea0f2f3de647279057a..a4c807527095bedece82d64167322fec829546ce 100644 (file)
@@ -366,8 +366,9 @@ static struct mtd_partition zylonite_nand_partitions[] = {
 
 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
        .enable_arbiter = 1,
-       .parts          = zylonite_nand_partitions,
-       .nr_parts       = ARRAY_SIZE(zylonite_nand_partitions),
+       .num_cs         = 1,
+       .parts[0]       = zylonite_nand_partitions,
+       .nr_parts[0]    = ARRAY_SIZE(zylonite_nand_partitions),
 };
 
 static void __init zylonite_init_nand(void)
index 66668565ee75e6694c086030504bf5d01fc59bef..f208154b1382d0492898ebba6b6d7c14079ad80d 100644 (file)
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 
index 2aec2f732515337cdeaa91519ea487bd84e783f3..737bdc631b0dba4d292057bd0393840880b3a2e7 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common objects
-obj-y                          := timer.o console.o clock.o pm_runtime.o
+obj-y                          := timer.o console.o clock.o
 
 # CPU objects
 obj-$(CONFIG_ARCH_SH7367)      += setup-sh7367.o clock-sh7367.o intc-sh7367.o
index 83624e26b884046c247b634f834d6c1e18b3d563..b862e9f81e3e557935f13df5ec6fa29128b4d86c 100644 (file)
@@ -515,14 +515,14 @@ static void __init ag5evm_init(void)
        /* enable MMCIF */
        gpio_request(GPIO_FN_MMCCLK0, NULL);
        gpio_request(GPIO_FN_MMCCMD0_PU, NULL);
-       gpio_request(GPIO_FN_MMCD0_0, NULL);
-       gpio_request(GPIO_FN_MMCD0_1, NULL);
-       gpio_request(GPIO_FN_MMCD0_2, NULL);
-       gpio_request(GPIO_FN_MMCD0_3, NULL);
-       gpio_request(GPIO_FN_MMCD0_4, NULL);
-       gpio_request(GPIO_FN_MMCD0_5, NULL);
-       gpio_request(GPIO_FN_MMCD0_6, NULL);
-       gpio_request(GPIO_FN_MMCD0_7, NULL);
+       gpio_request(GPIO_FN_MMCD0_0_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_1_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_2_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_3_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_4_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_5_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_6_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_7_PU, NULL);
        gpio_request(GPIO_PORT208, NULL); /* Reset */
        gpio_direction_output(GPIO_PORT208, 1);
 
index a3aa0f6df964d19e3ae60877f2d012c2a70b5343..4c865ece9ac4e9dc14aa4612ce7a780e59fed690 100644 (file)
@@ -201,7 +201,7 @@ static struct physmap_flash_data nor_flash_data = {
 static struct resource nor_flash_resources[] = {
        [0]     = {
                .start  = 0x20000000, /* CS0 shadow instead of regular CS0 */
-               .end    = 0x28000000 - 1, /* needed by USB MASK ROM boot */             
+               .end    = 0x28000000 - 1, /* needed by USB MASK ROM boot */
                .flags  = IORESOURCE_MEM,
        }
 };
index adc73122bf20d5200b195e9f50f99c34fb3f353e..bd9a78424d6b8e25a56b548ed3f38954981b5678 100644 (file)
@@ -48,6 +48,7 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/traps.h>
 
+/* SMSC 9220 */
 static struct resource smsc9220_resources[] = {
        [0] = {
                .start          = 0x14000000, /* CS5A */
@@ -77,6 +78,7 @@ static struct platform_device eth_device = {
        .num_resources  = ARRAY_SIZE(smsc9220_resources),
 };
 
+/* KEYSC */
 static struct sh_keysc_info keysc_platdata = {
        .mode           = SH_KEYSC_MODE_6,
        .scan_timing    = 3,
@@ -120,6 +122,7 @@ static struct platform_device keysc_device = {
        },
 };
 
+/* GPIO KEY */
 #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
 
 static struct gpio_keys_button gpio_buttons[] = {
@@ -150,6 +153,7 @@ static struct platform_device gpio_keys_device = {
        },
 };
 
+/* GPIO LED */
 #define GPIO_LED(n, g) { .name = n, .gpio = g }
 
 static struct gpio_led gpio_leds[] = {
@@ -175,6 +179,7 @@ static struct platform_device gpio_leds_device = {
        },
 };
 
+/* MMCIF */
 static struct resource mmcif_resources[] = {
        [0] = {
                .name   = "MMCIF",
@@ -207,6 +212,7 @@ static struct platform_device mmcif_device = {
        .resource       = mmcif_resources,
 };
 
+/* SDHI0 */
 static struct sh_mobile_sdhi_info sdhi0_info = {
        .tmio_caps      = MMC_CAP_SD_HIGHSPEED,
        .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
@@ -243,6 +249,7 @@ static struct platform_device sdhi0_device = {
        },
 };
 
+/* SDHI1 */
 static struct sh_mobile_sdhi_info sdhi1_info = {
        .tmio_caps      = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
        .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
index 66975921e6467b363e037ca355c82952a17a300a..995a9c3aec8fbe60da9c78f3dba9835d20db9003 100644 (file)
@@ -476,7 +476,7 @@ static struct clk_ops fsidiv_clk_ops = {
        .disable        = fsidiv_disable,
 };
 
-static struct clk_mapping sh7372_fsidiva_clk_mapping = {
+static struct clk_mapping fsidiva_clk_mapping = {
        .phys   = FSIDIVA,
        .len    = 8,
 };
@@ -484,10 +484,10 @@ static struct clk_mapping sh7372_fsidiva_clk_mapping = {
 struct clk sh7372_fsidiva_clk = {
        .ops            = &fsidiv_clk_ops,
        .parent         = &div6_reparent_clks[DIV6_FSIA], /* late install */
-       .mapping        = &sh7372_fsidiva_clk_mapping,
+       .mapping        = &fsidiva_clk_mapping,
 };
 
-static struct clk_mapping sh7372_fsidivb_clk_mapping = {
+static struct clk_mapping fsidivb_clk_mapping = {
        .phys   = FSIDIVB,
        .len    = 8,
 };
@@ -495,7 +495,7 @@ static struct clk_mapping sh7372_fsidivb_clk_mapping = {
 struct clk sh7372_fsidivb_clk = {
        .ops            = &fsidiv_clk_ops,
        .parent         = &div6_reparent_clks[DIV6_FSIB],  /* late install */
-       .mapping        = &sh7372_fsidivb_clk_mapping,
+       .mapping        = &fsidivb_clk_mapping,
 };
 
 static struct clk *late_main_clks[] = {
index 2e44f11f592e6979f8f0dc759c84fe6d3a4dfe7c..1b2334277e85d5cbad17a126698fdbc39aaefd7b 100644 (file)
@@ -26,65 +26,59 @@ void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = {
 };
 
 static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
-                                 struct cpuidle_state *state)
+                                 struct cpuidle_driver *drv,
+                                 int index)
 {
        ktime_t before, after;
-       int requested_state = state - &dev->states[0];
 
-       dev->last_state = &dev->states[requested_state];
        before = ktime_get();
 
        local_irq_disable();
        local_fiq_disable();
 
-       shmobile_cpuidle_modes[requested_state]();
+       shmobile_cpuidle_modes[index]();
 
        local_irq_enable();
        local_fiq_enable();
 
        after = ktime_get();
-       return ktime_to_ns(ktime_sub(after, before)) >> 10;
+       dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+       return index;
 }
 
 static struct cpuidle_device shmobile_cpuidle_dev;
 static struct cpuidle_driver shmobile_cpuidle_driver = {
        .name =         "shmobile_cpuidle",
        .owner =        THIS_MODULE,
+       .states[0] = {
+               .name = "C1",
+               .desc = "WFI",
+               .exit_latency = 1,
+               .target_residency = 1 * 2,
+               .flags = CPUIDLE_FLAG_TIME_VALID,
+       },
+       .safe_state_index = 0, /* C1 */
+       .state_count = 1,
 };
 
-void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
+void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
 
 static int shmobile_cpuidle_init(void)
 {
        struct cpuidle_device *dev = &shmobile_cpuidle_dev;
-       struct cpuidle_state *state;
+       struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
        int i;
 
-       cpuidle_register_driver(&shmobile_cpuidle_driver);
-
-       for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-               dev->states[i].name[0] = '\0';
-               dev->states[i].desc[0] = '\0';
-               dev->states[i].enter = shmobile_cpuidle_enter;
-       }
-
-       i = CPUIDLE_DRIVER_STATE_START;
-
-       state = &dev->states[i++];
-       snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
-       strncpy(state->desc, "WFI", CPUIDLE_DESC_LEN);
-       state->exit_latency = 1;
-       state->target_residency = 1 * 2;
-       state->power_usage = 3;
-       state->flags = 0;
-       state->flags |= CPUIDLE_FLAG_TIME_VALID;
-
-       dev->safe_state = state;
-       dev->state_count = i;
+       for (i = 0; i < CPUIDLE_STATE_MAX; i++)
+               drv->states[i].enter = shmobile_cpuidle_enter;
 
        if (shmobile_cpuidle_setup)
-               shmobile_cpuidle_setup(dev);
+               shmobile_cpuidle_setup(drv);
+
+       cpuidle_register_driver(drv);
 
+       dev->state_count = drv->state_count;
        cpuidle_register_device(dev);
 
        return 0;
index c0cdbf997c919ad6e22cd9044d4683807917908e..834bd6cd508f1f75625fb1f1126507ca9acf25d4 100644 (file)
@@ -9,9 +9,9 @@ extern int clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
 extern void shmobile_handle_irq_gic(struct pt_regs *);
 extern struct platform_suspend_ops shmobile_suspend_ops;
-struct cpuidle_device;
+struct cpuidle_driver;
 extern void (*shmobile_cpuidle_modes[])(void);
-extern void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
+extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
 
 extern void sh7367_init_irq(void);
 extern void sh7367_add_early_devices(void);
index 18ae6a990bc2706694881c2249b928b2b83ee59d..881d515a9686f3786179003b2f5d4c5816fe6ac7 100644 (file)
@@ -470,6 +470,14 @@ enum {
        GPIO_FN_SDHICMD2_PU,
        GPIO_FN_MMCCMD0_PU,
        GPIO_FN_MMCCMD1_PU,
+       GPIO_FN_MMCD0_0_PU,
+       GPIO_FN_MMCD0_1_PU,
+       GPIO_FN_MMCD0_2_PU,
+       GPIO_FN_MMCD0_3_PU,
+       GPIO_FN_MMCD0_4_PU,
+       GPIO_FN_MMCD0_5_PU,
+       GPIO_FN_MMCD0_6_PU,
+       GPIO_FN_MMCD0_7_PU,
        GPIO_FN_FSIACK_PU,
        GPIO_FN_FSIAILR_PU,
        GPIO_FN_FSIAIBT_PU,
index 128555e76e430fb41d4313a6e2dea46fbdd73146..e6e524654e676e270d702de51005ffcabc0557e2 100644 (file)
 #include <linux/gpio.h>
 #include <mach/sh7367.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)                              \
-       _1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),       \
-       _1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),       \
-       _1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),       \
-       _1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),       \
-       _1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _90(fn, pfx, sfx)                              \
-       _10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),     \
-       _10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),     \
-       _10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),     \
-       _10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),     \
-       _10(fn, pfx##9, sfx)
-
-#define _273(fn, pfx, sfx)             \
-       _10(fn, pfx, sfx), _90(fn, pfx, sfx),           \
-       _10(fn, pfx##10, sfx), _90(fn, pfx##1, sfx),    \
-       _10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),   \
-       _10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),   \
-       _10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),   \
-       _10(fn, pfx##26, sfx), _1(fn, pfx##270, sfx),   \
-       _1(fn, pfx##271, sfx), _1(fn, pfx##272, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_273(str) _273(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)                             \
+       PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),           \
+       PORT_10(fn, pfx##10, sfx), PORT_90(fn, pfx##1, sfx),    \
+       PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),   \
+       PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),   \
+       PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),   \
+       PORT_10(fn, pfx##26, sfx), PORT_1(fn, pfx##270, sfx),   \
+       PORT_1(fn, pfx##271, sfx), PORT_1(fn, pfx##272, sfx)
 
 enum {
        PINMUX_RESERVED = 0,
 
        PINMUX_DATA_BEGIN,
-       PORT_273(DATA), /* PORT0_DATA -> PORT272_DATA */
+       PORT_ALL(DATA), /* PORT0_DATA -> PORT272_DATA */
        PINMUX_DATA_END,
 
        PINMUX_INPUT_BEGIN,
-       PORT_273(IN), /* PORT0_IN -> PORT272_IN */
+       PORT_ALL(IN), /* PORT0_IN -> PORT272_IN */
        PINMUX_INPUT_END,
 
        PINMUX_INPUT_PULLUP_BEGIN,
-       PORT_273(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
+       PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
        PINMUX_INPUT_PULLUP_END,
 
        PINMUX_INPUT_PULLDOWN_BEGIN,
-       PORT_273(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
+       PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
        PINMUX_INPUT_PULLDOWN_END,
 
        PINMUX_OUTPUT_BEGIN,
-       PORT_273(OUT), /* PORT0_OUT -> PORT272_OUT */
+       PORT_ALL(OUT), /* PORT0_OUT -> PORT272_OUT */
        PINMUX_OUTPUT_END,
 
        PINMUX_FUNCTION_BEGIN,
-       PORT_273(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
-       PORT_273(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
-       PORT_273(FN0), /* PORT0_FN0 -> PORT272_FN0 */
-       PORT_273(FN1), /* PORT0_FN1 -> PORT272_FN1 */
-       PORT_273(FN2), /* PORT0_FN2 -> PORT272_FN2 */
-       PORT_273(FN3), /* PORT0_FN3 -> PORT272_FN3 */
-       PORT_273(FN4), /* PORT0_FN4 -> PORT272_FN4 */
-       PORT_273(FN5), /* PORT0_FN5 -> PORT272_FN5 */
-       PORT_273(FN6), /* PORT0_FN6 -> PORT272_FN6 */
-       PORT_273(FN7), /* PORT0_FN7 -> PORT272_FN7 */
+       PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
+       PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
+       PORT_ALL(FN0), /* PORT0_FN0 -> PORT272_FN0 */
+       PORT_ALL(FN1), /* PORT0_FN1 -> PORT272_FN1 */
+       PORT_ALL(FN2), /* PORT0_FN2 -> PORT272_FN2 */
+       PORT_ALL(FN3), /* PORT0_FN3 -> PORT272_FN3 */
+       PORT_ALL(FN4), /* PORT0_FN4 -> PORT272_FN4 */
+       PORT_ALL(FN5), /* PORT0_FN5 -> PORT272_FN5 */
+       PORT_ALL(FN6), /* PORT0_FN6 -> PORT272_FN6 */
+       PORT_ALL(FN7), /* PORT0_FN7 -> PORT272_FN7 */
 
        MSELBCR_MSEL2_1, MSELBCR_MSEL2_0,
        PINMUX_FUNCTION_END,
@@ -327,41 +308,6 @@ enum {
        PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-
 static pinmux_enum_t pinmux_data[] = {
 
        /* specify valid pin states for each pin in GPIO mode */
@@ -1098,13 +1044,9 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(DIVLOCK_MARK, PORT272_FN1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_273() _273(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
        /* 49-1 -> 49-6 (GPIO) */
-       GPIO_PORT_273(),
+       GPIO_PORT_ALL(),
 
        /* Special Pull-up / Pull-down Functions */
        GPIO_FN(PORT48_KEYIN0_PU), GPIO_FN(PORT49_KEYIN1_PU),
@@ -1345,22 +1287,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        GPIO_FN(DIVLOCK),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)            \
-       0, (out), (in), 0,                      \
-       0, 0, 0, 0,                             \
-       0, 0, (in_pd), 0,                       \
-       0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)                                                \
-       { PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {           \
-               PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,           \
-                    PORT##nr##_IN_PU, PORT##nr##_OUT),         \
-               PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2, \
-               PORT##nr##_FN3, PORT##nr##_FN4, PORT##nr##_FN5, \
-               PORT##nr##_FN6, PORT##nr##_FN7 }                \
-       }
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        PORTCR(0, 0xe6050000), /* PORT0CR */
        PORTCR(1, 0xe6050001), /* PORT1CR */
index 9c265dae138a31c245c63fbaf2f87e3f5f147dbb..1bd6585a6acffd23a3094c90487a723fca5beb09 100644 (file)
 #include <linux/gpio.h>
 #include <mach/sh7372.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)                              \
-       _1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),       \
-       _1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),       \
-       _1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),       \
-       _1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),       \
-       _1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _80(fn, pfx, sfx)                              \
-       _10(fn, pfx##1, sfx),   _10(fn, pfx##2, sfx),   \
-       _10(fn, pfx##3, sfx),   _10(fn, pfx##4, sfx),   \
-       _10(fn, pfx##5, sfx),   _10(fn, pfx##6, sfx),   \
-       _10(fn, pfx##7, sfx),   _10(fn, pfx##8, sfx)
-
-#define _190(fn, pfx, sfx) \
-       _10(fn, pfx, sfx), _80(fn, pfx, sfx), _10(fn, pfx##9, sfx), \
-       _10(fn, pfx##10, sfx), _80(fn, pfx##1, sfx), _1(fn, pfx##190, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_ALL(str) _190(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx) \
+       PORT_10(fn, pfx, sfx),          PORT_90(fn, pfx, sfx), \
+       PORT_10(fn, pfx##10, sfx),      PORT_10(fn, pfx##11, sfx), \
+       PORT_10(fn, pfx##12, sfx),      PORT_10(fn, pfx##13, sfx), \
+       PORT_10(fn, pfx##14, sfx),      PORT_10(fn, pfx##15, sfx), \
+       PORT_10(fn, pfx##16, sfx),      PORT_10(fn, pfx##17, sfx), \
+       PORT_10(fn, pfx##18, sfx),      PORT_1(fn, pfx##190, sfx)
 
 enum {
        PINMUX_RESERVED = 0,
@@ -381,108 +367,124 @@ enum {
        PINMUX_MARK_END,
 };
 
-/* PORT_DATA_I_PD(nr) */
-#define _I___D(nr)                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD)
-
-/* PORT_DATA_I_PU(nr) */
-#define _I__U_(nr)                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PU)
-
-/* PORT_DATA_I_PU_PD(nr) */
-#define _I__UD(nr)                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-/* PORT_DATA_O(nr) */
-#define __O___(nr)                                                     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-/* PORT_DATA_IO(nr) */
-#define _IO___(nr)                                  \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN)
-
-/* PORT_DATA_IO_PD(nr) */
-#define _IO__D(nr)                                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD)
-
-/* PORT_DATA_IO_PU(nr) */
-#define _IO_U_(nr)                                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PU)
-
-/* PORT_DATA_IO_PU_PD(nr) */
-#define _IO_UD(nr)                                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-
 static pinmux_enum_t pinmux_data[] = {
 
        /* specify valid pin states for each pin in GPIO mode */
-
-       _IO__D(0), _IO__D(1), __O___(2), _I___D(3), _I___D(4),
-       _I___D(5), _IO_UD(6), _I___D(7), _IO__D(8), __O___(9),
-
-       __O___(10), __O___(11), _IO_UD(12), _IO__D(13), _IO__D(14),
-       __O___(15), _IO__D(16), _IO__D(17), _I___D(18), _IO___(19),
-
-       _IO___(20), _IO___(21), _IO___(22), _IO___(23), _IO___(24),
-       _IO___(25), _IO___(26), _IO___(27), _IO___(28), _IO___(29),
-
-       _IO___(30), _IO___(31), _IO___(32), _IO___(33), _IO___(34),
-       _IO___(35), _IO___(36), _IO___(37), _IO___(38), _IO___(39),
-
-       _IO___(40), _IO___(41), _IO___(42), _IO___(43), _IO___(44),
-       _IO___(45), _IO_U_(46), _IO_U_(47), _IO_U_(48), _IO_U_(49),
-
-       _IO_U_(50), _IO_U_(51), _IO_U_(52), _IO_U_(53), _IO_U_(54),
-       _IO_U_(55), _IO_U_(56), _IO_U_(57), _IO_U_(58), _IO_U_(59),
-
-       _IO_U_(60), _IO_U_(61), _IO___(62), __O___(63), __O___(64),
-       _IO_U_(65), __O___(66), _IO_U_(67), __O___(68), _IO___(69), /*66?*/
-
-       _IO___(70), _IO___(71), __O___(72), _I__U_(73), _I__UD(74),
-       _IO_UD(75), _IO_UD(76), _IO_UD(77), _IO_UD(78), _IO_UD(79),
-
-       _IO_UD(80), _IO_UD(81), _IO_UD(82), _IO_UD(83), _IO_UD(84),
-       _IO_UD(85), _IO_UD(86), _IO_UD(87), _IO_UD(88), _IO_UD(89),
-
-       _IO_UD(90), _IO_UD(91), _IO_UD(92), _IO_UD(93), _IO_UD(94),
-       _IO_UD(95), _IO_U_(96), _IO_UD(97), _IO_UD(98), __O___(99), /*99?*/
-
-       _IO__D(100), _IO__D(101), _IO__D(102), _IO__D(103), _IO__D(104),
-       _IO__D(105), _IO_U_(106), _IO_U_(107), _IO_U_(108), _IO_U_(109),
-
-       _IO_U_(110), _IO_U_(111), _IO__D(112), _IO__D(113), _IO_U_(114),
-       _IO_U_(115), _IO_U_(116), _IO_U_(117), _IO_U_(118), _IO_U_(119),
-
-       _IO_U_(120), _IO__D(121), _IO__D(122), _IO__D(123), _IO__D(124),
-       _IO__D(125), _IO__D(126), _IO__D(127), _IO__D(128), _IO_UD(129),
-
-       _IO_UD(130), _IO_UD(131), _IO_UD(132), _IO_UD(133), _IO_UD(134),
-       _IO_UD(135), _IO__D(136), _IO__D(137), _IO__D(138), _IO__D(139),
-
-       _IO__D(140), _IO__D(141), _IO__D(142), _IO_UD(143), _IO__D(144),
-       _IO__D(145), _IO__D(146), _IO__D(147), _IO__D(148), _IO__D(149),
-
-       _IO__D(150), _IO__D(151), _IO_UD(152), _I___D(153), _IO_UD(154),
-       _I___D(155), _IO__D(156), _IO__D(157), _I___D(158), _IO__D(159),
-
-       __O___(160), _IO__D(161), _IO__D(162), _IO__D(163), _I___D(164),
-       _IO__D(165), _I___D(166), _I___D(167), _I___D(168), _I___D(169),
-
-       _I___D(170), __O___(171), _IO_UD(172), _IO_UD(173), _IO_UD(174),
-       _IO_UD(175), _IO_UD(176), _IO_UD(177), _IO_UD(178), __O___(179),
-
-       _IO_UD(180), _IO_UD(181), _IO_UD(182), _IO_UD(183), _IO_UD(184),
-       __O___(185), _IO_UD(186), _IO_UD(187), _IO_UD(188), _IO_UD(189),
-
-       _IO_UD(190),
+       PORT_DATA_IO_PD(0),             PORT_DATA_IO_PD(1),
+       PORT_DATA_O(2),                 PORT_DATA_I_PD(3),
+       PORT_DATA_I_PD(4),              PORT_DATA_I_PD(5),
+       PORT_DATA_IO_PU_PD(6),          PORT_DATA_I_PD(7),
+       PORT_DATA_IO_PD(8),             PORT_DATA_O(9),
+
+       PORT_DATA_O(10),                PORT_DATA_O(11),
+       PORT_DATA_IO_PU_PD(12),         PORT_DATA_IO_PD(13),
+       PORT_DATA_IO_PD(14),            PORT_DATA_O(15),
+       PORT_DATA_IO_PD(16),            PORT_DATA_IO_PD(17),
+       PORT_DATA_I_PD(18),             PORT_DATA_IO(19),
+
+       PORT_DATA_IO(20),               PORT_DATA_IO(21),
+       PORT_DATA_IO(22),               PORT_DATA_IO(23),
+       PORT_DATA_IO(24),               PORT_DATA_IO(25),
+       PORT_DATA_IO(26),               PORT_DATA_IO(27),
+       PORT_DATA_IO(28),               PORT_DATA_IO(29),
+
+       PORT_DATA_IO(30),               PORT_DATA_IO(31),
+       PORT_DATA_IO(32),               PORT_DATA_IO(33),
+       PORT_DATA_IO(34),               PORT_DATA_IO(35),
+       PORT_DATA_IO(36),               PORT_DATA_IO(37),
+       PORT_DATA_IO(38),               PORT_DATA_IO(39),
+
+       PORT_DATA_IO(40),               PORT_DATA_IO(41),
+       PORT_DATA_IO(42),               PORT_DATA_IO(43),
+       PORT_DATA_IO(44),               PORT_DATA_IO(45),
+       PORT_DATA_IO_PU(46),            PORT_DATA_IO_PU(47),
+       PORT_DATA_IO_PU(48),            PORT_DATA_IO_PU(49),
+
+       PORT_DATA_IO_PU(50),            PORT_DATA_IO_PU(51),
+       PORT_DATA_IO_PU(52),            PORT_DATA_IO_PU(53),
+       PORT_DATA_IO_PU(54),            PORT_DATA_IO_PU(55),
+       PORT_DATA_IO_PU(56),            PORT_DATA_IO_PU(57),
+       PORT_DATA_IO_PU(58),            PORT_DATA_IO_PU(59),
+
+       PORT_DATA_IO_PU(60),            PORT_DATA_IO_PU(61),
+       PORT_DATA_IO(62),               PORT_DATA_O(63),
+       PORT_DATA_O(64),                PORT_DATA_IO_PU(65),
+       PORT_DATA_O(66),                PORT_DATA_IO_PU(67),  /*66?*/
+       PORT_DATA_O(68),                PORT_DATA_IO(69),
+
+       PORT_DATA_IO(70),               PORT_DATA_IO(71),
+       PORT_DATA_O(72),                PORT_DATA_I_PU(73),
+       PORT_DATA_I_PU_PD(74),          PORT_DATA_IO_PU_PD(75),
+       PORT_DATA_IO_PU_PD(76),         PORT_DATA_IO_PU_PD(77),
+       PORT_DATA_IO_PU_PD(78),         PORT_DATA_IO_PU_PD(79),
+
+       PORT_DATA_IO_PU_PD(80),         PORT_DATA_IO_PU_PD(81),
+       PORT_DATA_IO_PU_PD(82),         PORT_DATA_IO_PU_PD(83),
+       PORT_DATA_IO_PU_PD(84),         PORT_DATA_IO_PU_PD(85),
+       PORT_DATA_IO_PU_PD(86),         PORT_DATA_IO_PU_PD(87),
+       PORT_DATA_IO_PU_PD(88),         PORT_DATA_IO_PU_PD(89),
+
+       PORT_DATA_IO_PU_PD(90),         PORT_DATA_IO_PU_PD(91),
+       PORT_DATA_IO_PU_PD(92),         PORT_DATA_IO_PU_PD(93),
+       PORT_DATA_IO_PU_PD(94),         PORT_DATA_IO_PU_PD(95),
+       PORT_DATA_IO_PU(96),            PORT_DATA_IO_PU_PD(97),
+       PORT_DATA_IO_PU_PD(98),         PORT_DATA_O(99), /*99?*/
+
+       PORT_DATA_IO_PD(100),           PORT_DATA_IO_PD(101),
+       PORT_DATA_IO_PD(102),           PORT_DATA_IO_PD(103),
+       PORT_DATA_IO_PD(104),           PORT_DATA_IO_PD(105),
+       PORT_DATA_IO_PU(106),           PORT_DATA_IO_PU(107),
+       PORT_DATA_IO_PU(108),           PORT_DATA_IO_PU(109),
+
+       PORT_DATA_IO_PU(110),           PORT_DATA_IO_PU(111),
+       PORT_DATA_IO_PD(112),           PORT_DATA_IO_PD(113),
+       PORT_DATA_IO_PU(114),           PORT_DATA_IO_PU(115),
+       PORT_DATA_IO_PU(116),           PORT_DATA_IO_PU(117),
+       PORT_DATA_IO_PU(118),           PORT_DATA_IO_PU(119),
+
+       PORT_DATA_IO_PU(120),           PORT_DATA_IO_PD(121),
+       PORT_DATA_IO_PD(122),           PORT_DATA_IO_PD(123),
+       PORT_DATA_IO_PD(124),           PORT_DATA_IO_PD(125),
+       PORT_DATA_IO_PD(126),           PORT_DATA_IO_PD(127),
+       PORT_DATA_IO_PD(128),           PORT_DATA_IO_PU_PD(129),
+
+       PORT_DATA_IO_PU_PD(130),        PORT_DATA_IO_PU_PD(131),
+       PORT_DATA_IO_PU_PD(132),        PORT_DATA_IO_PU_PD(133),
+       PORT_DATA_IO_PU_PD(134),        PORT_DATA_IO_PU_PD(135),
+       PORT_DATA_IO_PD(136),           PORT_DATA_IO_PD(137),
+       PORT_DATA_IO_PD(138),           PORT_DATA_IO_PD(139),
+
+       PORT_DATA_IO_PD(140),           PORT_DATA_IO_PD(141),
+       PORT_DATA_IO_PD(142),           PORT_DATA_IO_PU_PD(143),
+       PORT_DATA_IO_PD(144),           PORT_DATA_IO_PD(145),
+       PORT_DATA_IO_PD(146),           PORT_DATA_IO_PD(147),
+       PORT_DATA_IO_PD(148),           PORT_DATA_IO_PD(149),
+
+       PORT_DATA_IO_PD(150),           PORT_DATA_IO_PD(151),
+       PORT_DATA_IO_PU_PD(152),        PORT_DATA_I_PD(153),
+       PORT_DATA_IO_PU_PD(154),        PORT_DATA_I_PD(155),
+       PORT_DATA_IO_PD(156),           PORT_DATA_IO_PD(157),
+       PORT_DATA_I_PD(158),            PORT_DATA_IO_PD(159),
+
+       PORT_DATA_O(160),               PORT_DATA_IO_PD(161),
+       PORT_DATA_IO_PD(162),           PORT_DATA_IO_PD(163),
+       PORT_DATA_I_PD(164),            PORT_DATA_IO_PD(165),
+       PORT_DATA_I_PD(166),            PORT_DATA_I_PD(167),
+       PORT_DATA_I_PD(168),            PORT_DATA_I_PD(169),
+
+       PORT_DATA_I_PD(170),            PORT_DATA_O(171),
+       PORT_DATA_IO_PU_PD(172),        PORT_DATA_IO_PU_PD(173),
+       PORT_DATA_IO_PU_PD(174),        PORT_DATA_IO_PU_PD(175),
+       PORT_DATA_IO_PU_PD(176),        PORT_DATA_IO_PU_PD(177),
+       PORT_DATA_IO_PU_PD(178),        PORT_DATA_O(179),
+
+       PORT_DATA_IO_PU_PD(180),        PORT_DATA_IO_PU_PD(181),
+       PORT_DATA_IO_PU_PD(182),        PORT_DATA_IO_PU_PD(183),
+       PORT_DATA_IO_PU_PD(184),        PORT_DATA_O(185),
+       PORT_DATA_IO_PU_PD(186),        PORT_DATA_IO_PU_PD(187),
+       PORT_DATA_IO_PU_PD(188),        PORT_DATA_IO_PU_PD(189),
+
+       PORT_DATA_IO_PU_PD(190),
 
        /* IRQ */
        PINMUX_DATA(IRQ0_6_MARK,        PORT6_FN0,      MSEL1CR_0_0),
@@ -926,10 +928,6 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(MFIv4_MARK,         MSEL4CR_6_1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_ALL() _190(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
 
        /* PORT */
@@ -1201,22 +1199,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        GPIO_FN(SDENC_DV_CLKI),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)            \
-       0, (out), (in), 0,                      \
-       0, 0, 0, 0,                             \
-       0, 0, (in_pd), 0,                       \
-       0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)                                                \
-       { PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {           \
-               PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,           \
-                    PORT##nr##_IN_PU, PORT##nr##_OUT),         \
-               PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2, \
-               PORT##nr##_FN3, PORT##nr##_FN4, PORT##nr##_FN5, \
-               PORT##nr##_FN6, PORT##nr##_FN7 }                \
-       }
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        PORTCR(0,       0xE6051000), /* PORT0CR */
        PORTCR(1,       0xE6051001), /* PORT1CR */
index 613e6842ad0521a6da29eb6262a3d1be48bf880e..2f10511946ad1a8a60287f02ef6b7c6fa58bc211 100644 (file)
 #include <linux/gpio.h>
 #include <mach/sh7377.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)                              \
-       _1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),       \
-       _1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),       \
-       _1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),       \
-       _1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),       \
-       _1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _90(fn, pfx, sfx)                              \
-       _10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),     \
-       _10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),     \
-       _10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),     \
-       _10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),     \
-       _10(fn, pfx##9, sfx)
-
-#define _265(fn, pfx, sfx)                             \
-       _10(fn, pfx, sfx), _90(fn, pfx, sfx),           \
-       _10(fn, pfx##10, sfx),                          \
-       _1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),   \
-       _1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),   \
-       _1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),   \
-       _1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),   \
-       _1(fn, pfx##118, sfx),                          \
-       _1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),   \
-       _10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),   \
-       _10(fn, pfx##15, sfx),                          \
-       _1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),   \
-       _1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),   \
-       _1(fn, pfx##164, sfx),                          \
-       _1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),   \
-       _1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),   \
-       _1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),   \
-       _1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),   \
-       _10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),   \
-       _10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),   \
-       _10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),   \
-       _1(fn, pfx##260, sfx), _1(fn, pfx##261, sfx),   \
-       _1(fn, pfx##262, sfx), _1(fn, pfx##263, sfx),   \
-       _1(fn, pfx##264, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_265(str) _265(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)                             \
+       PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),           \
+       PORT_10(fn, pfx##10, sfx),                              \
+       PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),   \
+       PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),   \
+       PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),   \
+       PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),   \
+       PORT_1(fn, pfx##118, sfx),                              \
+       PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),   \
+       PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),   \
+       PORT_10(fn, pfx##15, sfx),                              \
+       PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),   \
+       PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),   \
+       PORT_1(fn, pfx##164, sfx),                              \
+       PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),   \
+       PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),   \
+       PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),   \
+       PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),   \
+       PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),   \
+       PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),   \
+       PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),   \
+       PORT_1(fn, pfx##260, sfx), PORT_1(fn, pfx##261, sfx),   \
+       PORT_1(fn, pfx##262, sfx), PORT_1(fn, pfx##263, sfx),   \
+       PORT_1(fn, pfx##264, sfx)
 
 enum {
        PINMUX_RESERVED = 0,
 
        PINMUX_DATA_BEGIN,
-       PORT_265(DATA), /* PORT0_DATA -> PORT264_DATA */
+       PORT_ALL(DATA), /* PORT0_DATA -> PORT264_DATA */
        PINMUX_DATA_END,
 
        PINMUX_INPUT_BEGIN,
-       PORT_265(IN), /* PORT0_IN -> PORT264_IN */
+       PORT_ALL(IN), /* PORT0_IN -> PORT264_IN */
        PINMUX_INPUT_END,
 
        PINMUX_INPUT_PULLUP_BEGIN,
-       PORT_265(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
+       PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
        PINMUX_INPUT_PULLUP_END,
 
        PINMUX_INPUT_PULLDOWN_BEGIN,
-       PORT_265(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
+       PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
        PINMUX_INPUT_PULLDOWN_END,
 
        PINMUX_OUTPUT_BEGIN,
-       PORT_265(OUT), /* PORT0_OUT -> PORT264_OUT */
+       PORT_ALL(OUT), /* PORT0_OUT -> PORT264_OUT */
        PINMUX_OUTPUT_END,
 
        PINMUX_FUNCTION_BEGIN,
-       PORT_265(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
-       PORT_265(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
-       PORT_265(FN0), /* PORT0_FN0 -> PORT264_FN0 */
-       PORT_265(FN1), /* PORT0_FN1 -> PORT264_FN1 */
-       PORT_265(FN2), /* PORT0_FN2 -> PORT264_FN2 */
-       PORT_265(FN3), /* PORT0_FN3 -> PORT264_FN3 */
-       PORT_265(FN4), /* PORT0_FN4 -> PORT264_FN4 */
-       PORT_265(FN5), /* PORT0_FN5 -> PORT264_FN5 */
-       PORT_265(FN6), /* PORT0_FN6 -> PORT264_FN6 */
-       PORT_265(FN7), /* PORT0_FN7 -> PORT264_FN7 */
+       PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
+       PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
+       PORT_ALL(FN0), /* PORT0_FN0 -> PORT264_FN0 */
+       PORT_ALL(FN1), /* PORT0_FN1 -> PORT264_FN1 */
+       PORT_ALL(FN2), /* PORT0_FN2 -> PORT264_FN2 */
+       PORT_ALL(FN3), /* PORT0_FN3 -> PORT264_FN3 */
+       PORT_ALL(FN4), /* PORT0_FN4 -> PORT264_FN4 */
+       PORT_ALL(FN5), /* PORT0_FN5 -> PORT264_FN5 */
+       PORT_ALL(FN6), /* PORT0_FN6 -> PORT264_FN6 */
+       PORT_ALL(FN7), /* PORT0_FN7 -> PORT264_FN7 */
 
        MSELBCR_MSEL17_1, MSELBCR_MSEL17_0,
        MSELBCR_MSEL16_1, MSELBCR_MSEL16_0,
@@ -360,45 +341,6 @@ enum {
        PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr)        \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)  \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PD,        \
-                               PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)        \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)       \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)    \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)    \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
 static pinmux_enum_t pinmux_data[] = {
        /* specify valid pin states for each pin in GPIO mode */
        /* 55-1 (GPIO) */
@@ -1078,13 +1020,9 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(RESETOUTS_MARK, PORT264_FN1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_265() _265(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
        /* 55-1 -> 55-5 (GPIO) */
-       GPIO_PORT_265(),
+       GPIO_PORT_ALL(),
 
        /* Special Pull-up / Pull-down Functions */
        GPIO_FN(PORT66_KEYIN0_PU), GPIO_FN(PORT67_KEYIN1_PU),
@@ -1362,23 +1300,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        GPIO_FN(RESETOUTS),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)    \
-       0, (out), (in), 0,      \
-               0, 0, 0, 0,     \
-               0, 0, (in_pd), 0,       \
-               0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)        \
-       { PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {   \
-                       PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,   \
-                                PORT##nr##_IN_PU, PORT##nr##_OUT),     \
-                               PORT##nr##_FN0, PORT##nr##_FN1, \
-                               PORT##nr##_FN2, PORT##nr##_FN3, \
-                               PORT##nr##_FN4, PORT##nr##_FN5, \
-                               PORT##nr##_FN6, PORT##nr##_FN7 }        \
-       }
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        PORTCR(0, 0xe6050000), /* PORT0CR */
        PORTCR(1, 0xe6050001), /* PORT1CR */
index 5abe02fbd6b99aa6ba09c7a377e9649d7e70b289..e05634ce2e0d60e8831b4c083f53a9e25ae70111 100644 (file)
 #include <mach/sh73a0.h>
 #include <mach/irqs.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)                              \
-       _1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),       \
-       _1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),       \
-       _1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),       \
-       _1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),       \
-       _1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _310(fn, pfx, sfx)                             \
-       _10(fn, pfx,    sfx), _10(fn, pfx##1, sfx),     \
-       _10(fn, pfx##2, sfx), _10(fn, pfx##3, sfx),     \
-       _10(fn, pfx##4, sfx), _10(fn, pfx##5, sfx),     \
-       _10(fn, pfx##6, sfx), _10(fn, pfx##7, sfx),     \
-       _10(fn, pfx##8, sfx), _10(fn, pfx##9, sfx),     \
-       _10(fn, pfx##10, sfx),                          \
-       _1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),   \
-       _1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),   \
-       _1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),   \
-       _1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),   \
-       _1(fn, pfx##118, sfx),                          \
-       _1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),   \
-       _10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),   \
-       _10(fn, pfx##15, sfx),                          \
-       _1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),   \
-       _1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),   \
-       _1(fn, pfx##164, sfx),                          \
-       _1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),   \
-       _1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),   \
-       _1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),   \
-       _1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),   \
-       _10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),   \
-       _10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),   \
-       _10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),   \
-       _10(fn, pfx##26, sfx), _10(fn, pfx##27, sfx),   \
-       _1(fn, pfx##280, sfx), _1(fn, pfx##281, sfx),   \
-       _1(fn, pfx##282, sfx),                          \
-       _1(fn, pfx##288, sfx), _1(fn, pfx##289, sfx),   \
-       _10(fn, pfx##29, sfx), _10(fn, pfx##30, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_310(str) _310(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)                             \
+       PORT_10(fn, pfx,    sfx), PORT_10(fn, pfx##1, sfx),     \
+       PORT_10(fn, pfx##2, sfx), PORT_10(fn, pfx##3, sfx),     \
+       PORT_10(fn, pfx##4, sfx), PORT_10(fn, pfx##5, sfx),     \
+       PORT_10(fn, pfx##6, sfx), PORT_10(fn, pfx##7, sfx),     \
+       PORT_10(fn, pfx##8, sfx), PORT_10(fn, pfx##9, sfx),     \
+       PORT_10(fn, pfx##10, sfx),                              \
+       PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),   \
+       PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),   \
+       PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),   \
+       PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),   \
+       PORT_1(fn, pfx##118, sfx),                              \
+       PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),   \
+       PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),   \
+       PORT_10(fn, pfx##15, sfx),                              \
+       PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),   \
+       PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),   \
+       PORT_1(fn, pfx##164, sfx),                              \
+       PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),   \
+       PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),   \
+       PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),   \
+       PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),   \
+       PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),   \
+       PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),   \
+       PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),   \
+       PORT_10(fn, pfx##26, sfx), PORT_10(fn, pfx##27, sfx),   \
+       PORT_1(fn, pfx##280, sfx), PORT_1(fn, pfx##281, sfx),   \
+       PORT_1(fn, pfx##282, sfx),                              \
+       PORT_1(fn, pfx##288, sfx), PORT_1(fn, pfx##289, sfx),   \
+       PORT_10(fn, pfx##29, sfx), PORT_10(fn, pfx##30, sfx)
 
 enum {
        PINMUX_RESERVED = 0,
 
        PINMUX_DATA_BEGIN,
-       PORT_310(DATA),                 /* PORT0_DATA -> PORT309_DATA */
+       PORT_ALL(DATA),                 /* PORT0_DATA -> PORT309_DATA */
        PINMUX_DATA_END,
 
        PINMUX_INPUT_BEGIN,
-       PORT_310(IN),                   /* PORT0_IN -> PORT309_IN */
+       PORT_ALL(IN),                   /* PORT0_IN -> PORT309_IN */
        PINMUX_INPUT_END,
 
        PINMUX_INPUT_PULLUP_BEGIN,
-       PORT_310(IN_PU),                /* PORT0_IN_PU -> PORT309_IN_PU */
+       PORT_ALL(IN_PU),                /* PORT0_IN_PU -> PORT309_IN_PU */
        PINMUX_INPUT_PULLUP_END,
 
        PINMUX_INPUT_PULLDOWN_BEGIN,
-       PORT_310(IN_PD),                /* PORT0_IN_PD -> PORT309_IN_PD */
+       PORT_ALL(IN_PD),                /* PORT0_IN_PD -> PORT309_IN_PD */
        PINMUX_INPUT_PULLDOWN_END,
 
        PINMUX_OUTPUT_BEGIN,
-       PORT_310(OUT),                  /* PORT0_OUT -> PORT309_OUT */
+       PORT_ALL(OUT),                  /* PORT0_OUT -> PORT309_OUT */
        PINMUX_OUTPUT_END,
 
        PINMUX_FUNCTION_BEGIN,
-       PORT_310(FN_IN),                /* PORT0_FN_IN -> PORT309_FN_IN */
-       PORT_310(FN_OUT),               /* PORT0_FN_OUT -> PORT309_FN_OUT */
-       PORT_310(FN0),                  /* PORT0_FN0 -> PORT309_FN0 */
-       PORT_310(FN1),                  /* PORT0_FN1 -> PORT309_FN1 */
-       PORT_310(FN2),                  /* PORT0_FN2 -> PORT309_FN2 */
-       PORT_310(FN3),                  /* PORT0_FN3 -> PORT309_FN3 */
-       PORT_310(FN4),                  /* PORT0_FN4 -> PORT309_FN4 */
-       PORT_310(FN5),                  /* PORT0_FN5 -> PORT309_FN5 */
-       PORT_310(FN6),                  /* PORT0_FN6 -> PORT309_FN6 */
-       PORT_310(FN7),                  /* PORT0_FN7 -> PORT309_FN7 */
+       PORT_ALL(FN_IN),                /* PORT0_FN_IN -> PORT309_FN_IN */
+       PORT_ALL(FN_OUT),               /* PORT0_FN_OUT -> PORT309_FN_OUT */
+       PORT_ALL(FN0),                  /* PORT0_FN0 -> PORT309_FN0 */
+       PORT_ALL(FN1),                  /* PORT0_FN1 -> PORT309_FN1 */
+       PORT_ALL(FN2),                  /* PORT0_FN2 -> PORT309_FN2 */
+       PORT_ALL(FN3),                  /* PORT0_FN3 -> PORT309_FN3 */
+       PORT_ALL(FN4),                  /* PORT0_FN4 -> PORT309_FN4 */
+       PORT_ALL(FN5),                  /* PORT0_FN5 -> PORT309_FN5 */
+       PORT_ALL(FN6),                  /* PORT0_FN6 -> PORT309_FN6 */
+       PORT_ALL(FN7),                  /* PORT0_FN7 -> PORT309_FN7 */
 
        MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1,
        MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1,
@@ -508,6 +496,14 @@ enum {
        SDHICMD2_PU_MARK,
        MMCCMD0_PU_MARK,
        MMCCMD1_PU_MARK,
+       MMCD0_0_PU_MARK,
+       MMCD0_1_PU_MARK,
+       MMCD0_2_PU_MARK,
+       MMCD0_3_PU_MARK,
+       MMCD0_4_PU_MARK,
+       MMCD0_5_PU_MARK,
+       MMCD0_6_PU_MARK,
+       MMCD0_7_PU_MARK,
        FSIBISLD_PU_MARK,
        FSIACK_PU_MARK,
        FSIAILR_PU_MARK,
@@ -517,45 +513,6 @@ enum {
        PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr)        \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)  \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PD,        \
-                               PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)        \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)       \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)    \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)    \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
 static pinmux_enum_t pinmux_data[] = {
        /* specify valid pin states for each pin in GPIO mode */
 
@@ -1561,6 +1518,24 @@ static pinmux_enum_t pinmux_data[] = {
                MSEL4CR_MSEL15_0),
        PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT297_IN_PU,
                MSEL4CR_MSEL15_1),
+
+       PINMUX_DATA(MMCD0_0_PU_MARK,
+                   PORT271_FN1, PORT271_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_1_PU_MARK,
+                   PORT272_FN1, PORT272_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_2_PU_MARK,
+                   PORT273_FN1, PORT273_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_3_PU_MARK,
+                   PORT274_FN1, PORT274_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_4_PU_MARK,
+                   PORT275_FN1, PORT275_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_5_PU_MARK,
+                   PORT276_FN1, PORT276_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_6_PU_MARK,
+                   PORT277_FN1, PORT277_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_7_PU_MARK,
+                   PORT278_FN1, PORT278_IN_PU, MSEL4CR_MSEL15_0),
+
        PINMUX_DATA(FSIBISLD_PU_MARK, PORT39_FN1, PORT39_IN_PU),
        PINMUX_DATA(FSIACK_PU_MARK, PORT49_FN1, PORT49_IN_PU),
        PINMUX_DATA(FSIAILR_PU_MARK, PORT50_FN5, PORT50_IN_PU),
@@ -1568,12 +1543,8 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(FSIAISLD_PU_MARK, PORT55_FN1, PORT55_IN_PU),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_310() _310(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
-       GPIO_PORT_310(),
+       GPIO_PORT_ALL(),
 
        /* Table 25-1 (Functions 0-7) */
        GPIO_FN(VBUS_0),
@@ -2236,24 +2207,20 @@ static struct pinmux_gpio pinmux_gpios[] = {
        GPIO_FN(SDHICMD2_PU),
        GPIO_FN(MMCCMD0_PU),
        GPIO_FN(MMCCMD1_PU),
+       GPIO_FN(MMCD0_0_PU),
+       GPIO_FN(MMCD0_1_PU),
+       GPIO_FN(MMCD0_2_PU),
+       GPIO_FN(MMCD0_3_PU),
+       GPIO_FN(MMCD0_4_PU),
+       GPIO_FN(MMCD0_5_PU),
+       GPIO_FN(MMCD0_6_PU),
+       GPIO_FN(MMCD0_7_PU),
        GPIO_FN(FSIACK_PU),
        GPIO_FN(FSIAILR_PU),
        GPIO_FN(FSIAIBT_PU),
        GPIO_FN(FSIAISLD_PU),
 };
 
-#define PORTCR(nr, reg)        \
-       { PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \
-               0, \
-               /*0001*/ PORT##nr##_OUT , \
-               /*0010*/ PORT##nr##_IN , 0, 0, 0, 0, 0, 0, 0, \
-               /*1010*/ PORT##nr##_IN_PD, 0, 0, 0, \
-               /*1110*/ PORT##nr##_IN_PU, 0, \
-               PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2, \
-               PORT##nr##_FN3, PORT##nr##_FN4, PORT##nr##_FN5, \
-               PORT##nr##_FN6, PORT##nr##_FN7, 0, 0, 0, 0, 0, 0, 0, 0 } \
-       }
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        PORTCR(0, 0xe6050000), /* PORT0CR */
        PORTCR(1, 0xe6050001), /* PORT1CR */
index 79612737c5b231867b06d809b5c54ec5d92aadf7..34bbcbfb1706f1b74d4d5c92965e491d32204e21 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/bitrev.h>
+#include <linux/console.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
@@ -106,9 +107,8 @@ static int pd_power_down(struct generic_pm_domain *genpd)
        return 0;
 }
 
-static int pd_power_up(struct generic_pm_domain *genpd)
+static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume)
 {
-       struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
        unsigned int mask = 1 << sh7372_pd->bit_shift;
        unsigned int retry_count;
        int ret = 0;
@@ -123,13 +123,13 @@ static int pd_power_up(struct generic_pm_domain *genpd)
 
        for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
                if (!(__raw_readl(SWUCR) & mask))
-                       goto out;
+                       break;
                if (retry_count > PSTR_RETRIES)
                        udelay(PSTR_DELAY_US);
                else
                        cpu_relax();
        }
-       if (__raw_readl(SWUCR) & mask)
+       if (!retry_count)
                ret = -EIO;
 
        if (!sh7372_pd->no_debug)
@@ -137,12 +137,17 @@ static int pd_power_up(struct generic_pm_domain *genpd)
                         mask, __raw_readl(PSTR));
 
  out:
-       if (ret == 0 && sh7372_pd->resume)
+       if (ret == 0 && sh7372_pd->resume && do_resume)
                sh7372_pd->resume();
 
        return ret;
 }
 
+static int pd_power_up(struct generic_pm_domain *genpd)
+{
+        return __pd_power_up(to_sh7372_pd(genpd), true);
+}
+
 static void sh7372_a4r_suspend(void)
 {
        sh7372_intcs_suspend();
@@ -174,7 +179,7 @@ void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
        genpd->active_wakeup = pd_active_wakeup;
        genpd->power_off = pd_power_down;
        genpd->power_on = pd_power_up;
-       genpd->power_on(&sh7372_pd->genpd);
+       __pd_power_up(sh7372_pd, false);
 }
 
 void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
@@ -227,11 +232,23 @@ struct sh7372_pm_domain sh7372_a3sp = {
        .no_debug = true,
 };
 
+static void sh7372_a3sp_init(void)
+{
+       /* serial consoles make use of SCIF hardware located in A3SP,
+        * keep such power domain on if "no_console_suspend" is set.
+        */
+       sh7372_a3sp.stay_on = !console_suspend_enabled;
+}
+
 struct sh7372_pm_domain sh7372_a3sg = {
        .bit_shift = 13,
 };
 
-#endif /* CONFIG_PM */
+#else /* !CONFIG_PM */
+
+static inline void sh7372_a3sp_init(void) {}
+
+#endif /* !CONFIG_PM */
 
 #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
 static int sh7372_do_idle_core_standby(unsigned long unused)
@@ -402,22 +419,18 @@ static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2)
 
 #ifdef CONFIG_CPU_IDLE
 
-static void sh7372_cpuidle_setup(struct cpuidle_device *dev)
+static void sh7372_cpuidle_setup(struct cpuidle_driver *drv)
 {
-       struct cpuidle_state *state;
-       int i = dev->state_count;
+       struct cpuidle_state *state = &drv->states[drv->state_count];
 
-       state = &dev->states[i];
        snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
        strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
        state->exit_latency = 10;
        state->target_residency = 20 + 10;
-       state->power_usage = 1; /* perhaps not */
-       state->flags = 0;
-       state->flags |= CPUIDLE_FLAG_TIME_VALID;
-       shmobile_cpuidle_modes[i] = sh7372_enter_core_standby;
+       state->flags = CPUIDLE_FLAG_TIME_VALID;
+       shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby;
 
-       dev->state_count = i + 1;
+       drv->state_count++;
 }
 
 static void sh7372_cpuidle_init(void)
@@ -469,6 +482,8 @@ void __init sh7372_pm_init(void)
        /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
        __raw_writel(0, PDNSEL);
 
+       sh7372_a3sp_init();
+
        sh7372_suspend_init();
        sh7372_cpuidle_init();
 }
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c
deleted file mode 100644 (file)
index bd5c6a3..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * arch/arm/mach-shmobile/pm_runtime.c
- *
- * Runtime PM support code for SuperH Mobile ARM
- *
- *  Copyright (C) 2009-2010 Magnus Damm
- *
- * 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/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_clock.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/sh_clk.h>
-#include <linux/bitmap.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_PM_RUNTIME
-
-static int default_platform_runtime_idle(struct device *dev)
-{
-       /* suspend synchronously to disable clocks immediately */
-       return pm_runtime_suspend(dev);
-}
-
-static struct dev_pm_domain default_pm_domain = {
-       .ops = {
-               .runtime_suspend = pm_clk_suspend,
-               .runtime_resume = pm_clk_resume,
-               .runtime_idle = default_platform_runtime_idle,
-               USE_PLATFORM_PM_SLEEP_OPS
-       },
-};
-
-#define DEFAULT_PM_DOMAIN_PTR  (&default_pm_domain)
-
-#else
-
-#define DEFAULT_PM_DOMAIN_PTR  NULL
-
-#endif /* CONFIG_PM_RUNTIME */
-
-static struct pm_clk_notifier_block platform_bus_notifier = {
-       .pm_domain = DEFAULT_PM_DOMAIN_PTR,
-       .con_ids = { NULL, },
-};
-
-static int __init sh_pm_runtime_init(void)
-{
-       pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
-       return 0;
-}
-core_initcall(sh_pm_runtime_init);
-
-static int __init sh_pm_runtime_late_init(void)
-{
-       pm_genpd_poweroff_unused();
-       return 0;
-}
-late_initcall(sh_pm_runtime_late_init);
index d368f8dafcfd916fe215637fd3cdd84e8d56c1a3..74743ad3d2d356b90908529dfa57b15ccd168dd5 100644 (file)
@@ -101,6 +101,13 @@ static void __init tegra_dt_init(void)
 
        tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
+       /*
+        * Finished with the static registrations now; fill in the missing
+        * devices
+        */
+       of_platform_populate(NULL, tegra_dt_match_table,
+                               tegra20_auxdata_lookup, NULL);
+
        for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
                if (of_machine_is_compatible(pinmux_configs[i].machine)) {
                        pinmux_configs[i].init();
@@ -110,12 +117,6 @@ static void __init tegra_dt_init(void)
 
        WARN(i == ARRAY_SIZE(pinmux_configs),
                "Unknown platform! Pinmuxing not initialized\n");
-
-       /*
-        * Finished with the static registrations now; fill in the missing
-        * devices
-        */
-       of_platform_populate(NULL, tegra_dt_match_table, tegra20_auxdata_lookup, NULL);
 }
 
 static const char * tegra_dt_board_compat[] = {
index e99b45618cd0d5f9c840cfac84fcb85207d2dcef..7a4a26d5174c33f4c1667725becd986f6f57dff2 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/kernel.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+
 #include <mach/pinmux.h>
 
 #include "gpio-names.h"
@@ -161,7 +163,9 @@ static struct tegra_gpio_table gpio_table[] = {
 
 void harmony_pinmux_init(void)
 {
-       platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+       if (!of_machine_is_compatible("nvidia,tegra20"))
+               platform_add_devices(pinmux_devices,
+                                       ARRAY_SIZE(pinmux_devices));
 
        tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
 
index fb20894862b0c94bac143b93e039bc0d52d1925d..be30e215f4b73ba15daefb2030c8d86afc4e1637 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/kernel.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+
 #include <mach/pinmux.h>
 
 #include "gpio-names.h"
@@ -158,7 +160,9 @@ static struct tegra_gpio_table gpio_table[] = {
 
 void paz00_pinmux_init(void)
 {
-       platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+       if (!of_machine_is_compatible("nvidia,tegra20"))
+               platform_add_devices(pinmux_devices,
+                                       ARRAY_SIZE(pinmux_devices));
 
        tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
 
index fbce31daa3c9fd65760fc8d6fcc2b0cbdc92db8e..b1c2972f62fe4622eedff53761cce68340959b03 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 
 #include <mach/pinmux.h>
 #include <mach/pinmux-t2.h>
@@ -191,6 +192,7 @@ static struct tegra_gpio_table common_gpio_table[] = {
        { .gpio = TEGRA_GPIO_SD2_POWER,         .enable = true },
        { .gpio = TEGRA_GPIO_LIDSWITCH,         .enable = true },
        { .gpio = TEGRA_GPIO_POWERKEY,          .enable = true },
+       { .gpio = TEGRA_GPIO_HP_DET,            .enable = true },
        { .gpio = TEGRA_GPIO_ISL29018_IRQ,      .enable = true },
        { .gpio = TEGRA_GPIO_CDC_IRQ,           .enable = true },
        { .gpio = TEGRA_GPIO_USB1,              .enable = true },
@@ -218,7 +220,9 @@ static void __init update_pinmux(struct tegra_pingroup_config *newtbl, int size)
 
 void __init seaboard_common_pinmux_init(void)
 {
-       platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+       if (!of_machine_is_compatible("nvidia,tegra20"))
+               platform_add_devices(pinmux_devices,
+                                       ARRAY_SIZE(pinmux_devices));
 
        tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
 
index 4969dd28a04ccf58e03850497fbdf368a3f21e8f..7ab719d46da0558f3b9b1ca4df751a2a05a71432 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/of.h>
 
 #include <mach/pinmux.h>
 
@@ -157,7 +158,9 @@ static struct tegra_gpio_table gpio_table[] = {
 
 void __init trimslice_pinmux_init(void)
 {
-       platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+       if (!of_machine_is_compatible("nvidia,tegra20"))
+               platform_add_devices(pinmux_devices,
+                                       ARRAY_SIZE(pinmux_devices));
        tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
        tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
 }
index 7a1fa6adb7c32d5645b1f0e608b1e61794081afc..5b0c38abacc107a7eae8bd35ec8f03666f3422e7 100644 (file)
@@ -422,7 +422,7 @@ struct platform_device nuc900_device_kpi = {
 
 /* LCD controller*/
 
-static struct nuc900fb_display __initdata nuc900_lcd_info[] = {
+static struct nuc900fb_display nuc900_lcd_info[] = {
        /* Giantplus Technology GPM1040A0 320x240 Color TFT LCD */
        [0] = {
                .type           = LCM_DCCS_VA_SRC_RGB565,
@@ -445,7 +445,7 @@ static struct nuc900fb_display __initdata nuc900_lcd_info[] = {
        },
 };
 
-static struct nuc900fb_mach_info nuc900_fb_info __initdata = {
+static struct nuc900fb_mach_info nuc900_fb_info = {
 #if defined(CONFIG_GPM1040A0_320X240)
        .displays               = &nuc900_lcd_info[0],
 #else
index 94c0e71617c6c3487aaf20a4f1b7bfd34023e580..23ef1f573abd3395ac872ab6b39be6bc29090a8d 100644 (file)
@@ -19,6 +19,7 @@
 extern void mfp_set_groupf(struct device *dev);
 extern void mfp_set_groupc(struct device *dev);
 extern void mfp_set_groupi(struct device *dev);
-extern void mfp_set_groupg(struct device *dev);
+extern void mfp_set_groupg(struct device *dev, const char *subname);
+extern void mfp_set_groupd(struct device *dev, const char *subname);
 
 #endif /* __ASM_ARCH_MFP_H */
index bd94819e314fed7f67173c016a00bbcfbacc38c6..2c4e0c1285010fdfee53bebeaff4cd638c50a56f 100644 (file)
@@ -14,7 +14,7 @@
 #ifndef __ASM_ARCH_SPI_H
 #define __ASM_ARCH_SPI_H
 
-extern void mfp_set_groupg(struct device *dev);
+extern void mfp_set_groupg(struct device *dev, const char *subname);
 
 struct nuc900_spi_info {
        unsigned int num_cs;
index fb7fb627b1a564ca920fdb747080988f3fb75551..9dd74612bb8707560abd06e6adc250f7ecd54bf2 100644 (file)
 #define REG_MFSEL      (W90X900_VA_GCR + 0xC)
 
 #define GPSELF         (0x01 << 1)
-
 #define GPSELC         (0x03 << 2)
-#define ENKPI          (0x02 << 2)
-#define ENNAND         (0x01 << 2)
+#define GPSELD         (0x0f << 4)
 
 #define GPSELEI0       (0x01 << 26)
 #define GPSELEI1       (0x01 << 27)
 #define GPIOG0TO1      (0x03 << 14)
 #define GPIOG2TO3      (0x03 << 16)
 #define GPIOG22TO23    (0x03 << 22)
+#define GPIOG18TO20    (0x07 << 18)
 
 #define ENSPI          (0x0a << 14)
 #define ENI2C0         (0x01 << 14)
 #define ENI2C1         (0x01 << 16)
 #define ENAC97         (0x02 << 22)
+#define ENSD1          (0x02 << 18)
+#define ENSD0          (0x0a << 4)
+#define ENKPI          (0x02 << 2)
+#define ENNAND         (0x01 << 2)
 
 static DEFINE_MUTEX(mfp_mutex);
 
@@ -127,16 +130,19 @@ void mfp_set_groupi(struct device *dev)
 }
 EXPORT_SYMBOL(mfp_set_groupi);
 
-void mfp_set_groupg(struct device *dev)
+void mfp_set_groupg(struct device *dev, const char *subname)
 {
        unsigned long mfpen;
        const char *dev_id;
 
-       BUG_ON(!dev);
+       BUG_ON((!dev) && (!subname));
 
        mutex_lock(&mfp_mutex);
 
-       dev_id = dev_name(dev);
+       if (subname != NULL)
+               dev_id = subname;
+       else
+               dev_id = dev_name(dev);
 
        mfpen = __raw_readl(REG_MFSEL);
 
@@ -152,6 +158,9 @@ void mfp_set_groupg(struct device *dev)
        } else if (strcmp(dev_id, "nuc900-audio") == 0) {
                mfpen &= ~(GPIOG22TO23);
                mfpen |= ENAC97;/*enable AC97*/
+       } else if (strcmp(dev_id, "nuc900-mmc-port1") == 0) {
+               mfpen &= ~(GPIOG18TO20);
+               mfpen |= (ENSD1 | 0x01);/*enable sd1*/
        } else {
                mfpen &= ~(GPIOG0TO1 | GPIOG2TO3);/*GPIOG[3:0]*/
        }
@@ -162,3 +171,30 @@ void mfp_set_groupg(struct device *dev)
 }
 EXPORT_SYMBOL(mfp_set_groupg);
 
+void mfp_set_groupd(struct device *dev, const char *subname)
+{
+       unsigned long mfpen;
+       const char *dev_id;
+
+       BUG_ON((!dev) && (!subname));
+
+       mutex_lock(&mfp_mutex);
+
+       if (subname != NULL)
+               dev_id = subname;
+       else
+               dev_id = dev_name(dev);
+
+       mfpen = __raw_readl(REG_MFSEL);
+
+       if (strcmp(dev_id, "nuc900-mmc-port0") == 0) {
+               mfpen &= ~GPSELD;/*enable sd0*/
+               mfpen |= ENSD0;
+       } else
+               mfpen &= (~GPSELD);
+
+       __raw_writel(mfpen, REG_MFSEL);
+
+       mutex_unlock(&mfp_mutex);
+}
+EXPORT_SYMBOL(mfp_set_groupd);
index 8ac9e9f84790bb946716016607478ad97711376d..b1e192ba8c2450cb75a8118f86f8b650be284c82 100644 (file)
@@ -61,7 +61,7 @@ static inline void cache_sync(void)
 {
        void __iomem *base = l2x0_base;
 
-#ifdef CONFIG_ARM_ERRATA_753970
+#ifdef CONFIG_PL310_ERRATA_753970
        /* write to an unmmapped register */
        writel_relaxed(0, base + L2X0_DUMMY_REG);
 #else
index e4e7f6cba1ab4823fdbf0fe7ab2109bf6df89ed7..1aa664a1999fce45c2548726b50b6fa924608ec2 100644 (file)
@@ -168,7 +168,7 @@ static int __init consistent_init(void)
        pte_t *pte;
        int i = 0;
        unsigned long base = consistent_base;
-       unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_SHIFT;
+       unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
 
        consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
        if (!consistent_pte) {
@@ -332,6 +332,15 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
        struct page *page;
        void *addr;
 
+       /*
+        * Following is a work-around (a.k.a. hack) to prevent pages
+        * with __GFP_COMP being passed to split_page() which cannot
+        * handle them.  The real problem is that this flag probably
+        * should be 0 on ARM as it is not supported on this
+        * platform; see CONFIG_HUGETLBFS.
+        */
+       gfp &= ~(__GFP_COMP);
+
        *handle = ~0;
        size = PAGE_ALIGN(size);
 
index 74be05f3e03ac58be921aff208c6f6aa460ab683..44b628e4d6ea9c0121acf892ffbcfb30d0fc40ad 100644 (file)
@@ -9,8 +9,7 @@
 #include <linux/io.h>
 #include <linux/personality.h>
 #include <linux/random.h>
-#include <asm/cputype.h>
-#include <asm/system.h>
+#include <asm/cachetype.h>
 
 #define COLOUR_ALIGN(addr,pgoff)               \
        ((((addr)+SHMLBA-1)&~(SHMLBA-1)) +      \
@@ -32,25 +31,15 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        unsigned long start_addr;
-#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
-       unsigned int cache_type;
-       int do_align = 0, aliasing = 0;
+       int do_align = 0;
+       int aliasing = cache_is_vipt_aliasing();
 
        /*
         * We only need to do colour alignment if either the I or D
-        * caches alias.  This is indicated by bits 9 and 21 of the
-        * cache type register.
+        * caches alias.
         */
-       cache_type = read_cpuid_cachetype();
-       if (cache_type != read_cpuid_id()) {
-               aliasing = (cache_type | cache_type >> 12) & (1 << 11);
-               if (aliasing)
-                       do_align = filp || flags & MAP_SHARED;
-       }
-#else
-#define do_align 0
-#define aliasing 0
-#endif
+       if (aliasing)
+               do_align = filp || (flags & MAP_SHARED);
 
        /*
         * We enforce the MAP_FIXED case.
index a08a95107a632f9b1c178c29a55388494d7286bd..b3a1f2b3ada3bcb2f699b7a1e86bda0a1e866acb 100644 (file)
@@ -10,7 +10,7 @@ choice
 
 config ARCH_IMX_V4_V5
        bool "i.MX1, i.MX21, i.MX25, i.MX27"
-       select AUTO_ZRELADDR
+       select AUTO_ZRELADDR if !ZBOOT_ROM
        select ARM_PATCH_PHYS_VIRT
        help
          This enables support for systems based on the Freescale i.MX ARMv4
@@ -26,7 +26,7 @@ config ARCH_IMX_V6_V7
 
 config ARCH_MX5
        bool "i.MX50, i.MX51, i.MX53"
-       select AUTO_ZRELADDR
+       select AUTO_ZRELADDR if !ZBOOT_ROM
        select ARM_PATCH_PHYS_VIRT
        help
          This enables support for machines using Freescale's i.MX50 and i.MX53
index 8875fb415f68f36990f0be4284b62dbb66fd32c4..55f15699a3835cba42c5509fc62b031db4e033d7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <mach/common.h>
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 #include <mach/hardware.h>
 
 #include "irq-common.h"
index b3b8eed263b88e3c26765242b71184e981f9d28b..12f8f81090104726113716f82b4551080c5b0bb0 100644 (file)
@@ -28,21 +28,14 @@ asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
                if (irqnr == 1023)
                        break;
 
-               if (irqnr > 29 && irqnr < 1021)
+               if (irqnr > 15 && irqnr < 1021)
                        handle_IRQ(irqnr, regs);
 #ifdef CONFIG_SMP
-               else if (irqnr < 16) {
+               else {
                        writel_relaxed(irqstat, gic_cpu_base_addr +
                                                GIC_CPU_EOI);
                        handle_IPI(irqnr, regs);
                }
-#endif
-#ifdef CONFIG_LOCAL_TIMERS
-               else if (irqnr == 29) {
-                       writel_relaxed(irqstat, gic_cpu_base_addr +
-                                               GIC_CPU_EOI);
-                       handle_local_timer(regs);
-               }
 #endif
        } while (1);
 }
index 83b745a5e1b724e92ee87be633dc15b00edab968..c75f254abd857c07e6f8133716b51d5925f17581 100644 (file)
@@ -85,7 +85,6 @@ enum mxc_cpu_pwr_mode {
 };
 
 extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
-extern void (*imx_idle)(void);
 extern void imx_print_silicon_rev(const char *cpu, int srev);
 
 void avic_handle_irq(struct pt_regs *);
@@ -133,4 +132,5 @@ extern void imx53_qsb_common_init(void);
 extern void imx53_smd_common_init(void);
 extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
 extern void imx6q_pm_init(void);
+extern void imx6q_clock_map_io(void);
 #endif
index 9fe0dfcf4e7e02a85e0d4e944829d9f43305d74c..ca5cf26a04b1c9f16bf3e455afd4fa4098a7048e 100644 (file)
@@ -25,6 +25,3 @@
 
        .macro test_for_ipi, irqnr, irqstat, base, tmp
        .endm
-
-       .macro test_for_ltirq, irqnr, irqstat, base, tmp
-       .endm
index 00a78193c681ae16f5ed61f1b587f3ecf9e777f8..a4d36d601d55a5ed493f9191929850c6530f804f 100644 (file)
 #define IMX_CHIP_REVISION_3_3          0x33
 #define IMX_CHIP_REVISION_UNKNOWN      0xff
 
-#define IMX_CHIP_REVISION_1_0_STRING           "1.0"
-#define IMX_CHIP_REVISION_1_1_STRING           "1.1"
-#define IMX_CHIP_REVISION_1_2_STRING           "1.2"
-#define IMX_CHIP_REVISION_1_3_STRING           "1.3"
-#define IMX_CHIP_REVISION_2_0_STRING           "2.0"
-#define IMX_CHIP_REVISION_2_1_STRING           "2.1"
-#define IMX_CHIP_REVISION_2_2_STRING           "2.2"
-#define IMX_CHIP_REVISION_2_3_STRING           "2.3"
-#define IMX_CHIP_REVISION_3_0_STRING           "3.0"
-#define IMX_CHIP_REVISION_3_1_STRING           "3.1"
-#define IMX_CHIP_REVISION_3_2_STRING           "3.2"
-#define IMX_CHIP_REVISION_3_3_STRING           "3.3"
-#define IMX_CHIP_REVISION_UNKNOWN_STRING       "unknown"
-
 #ifndef __ASSEMBLY__
 extern unsigned int __mxc_cpu_type;
 #endif
index cf88b3593fba794d1a2de0c871f278ec03988da5..b9895d250167cf6b384d5cb1320e00e855537019 100644 (file)
 #ifndef __ASM_ARCH_MXC_SYSTEM_H__
 #define __ASM_ARCH_MXC_SYSTEM_H__
 
-extern void (*imx_idle)(void);
-
 static inline void arch_idle(void)
 {
-       if (imx_idle != NULL)
-               (imx_idle)();
-       else
-               cpu_do_idle();
+       cpu_do_idle();
 }
 
 void arch_reset(char mode, const char *cmd);
index 9dad8dcc2ea9dde822720e14c0c55ead52e8a420..d65fb31a55ca47ef350e38da864b6d34cf5295f9 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
@@ -28,8 +29,8 @@
 #include <asm/system.h>
 #include <asm/mach-types.h>
 
-void (*imx_idle)(void) = NULL;
 void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
+EXPORT_SYMBOL_GPL(imx_ioremap);
 
 static void __iomem *wdog_base;
 
index e993a184189aa2c756a7ee8741fd7e096eb2da59..a3c164c7ba828a60c5bb2e3a94fb4055c318a9cd 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
index 2def4e1990edca55e1fa67efd505f7efa7a25c33..af3b92be84593384f96c5c8c59f74d10c108e22d 100644 (file)
@@ -35,6 +35,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/err.h>
index 679cbd49c01945633b81b7c68cf25b0c38dfdc56..db071bc71c4d61d8e5bd5938eb3e438a06f2b449 100644 (file)
@@ -184,7 +184,7 @@ static inline int omap2_i2c_add_bus(int bus_id)
                        NULL, 0, 0);
        WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
 
-       return PTR_ERR(pdev);
+       return PTR_RET(pdev);
 }
 #else
 static inline int omap2_i2c_add_bus(int bus_id)
index 197ca03c3f7d8490a109a9b576b2e2f9c9c420e6..eb73ab40e9556ee03f36e63fa7c06b9e77b4b1d3 100644 (file)
@@ -165,8 +165,8 @@ struct dpll_data {
        u8                      auto_recal_bit;
        u8                      recal_en_bit;
        u8                      recal_st_bit;
-       u8                      flags;
 #  endif
+       u8                      flags;
 };
 
 #endif
index c50df4814f6f43935c7b021064c610f200ff0dc0..3ff3e36580f267df6890712efef55e8ee22bdbc7 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 
 #include <plat/i2c.h>
+#include <plat/omap_hwmod.h>
 
 struct sys_timer;
 
@@ -55,6 +56,8 @@ void am35xx_init_early(void);
 void ti816x_init_early(void);
 void omap4430_init_early(void);
 
+extern int omap_dss_reset(struct omap_hwmod *);
+
 void omap_sram_init(void);
 
 /*
index 2f90269422292d8ae8f854bbbead3751bfca784c..408a12f792051865c9adf21b0760b9b6871fe899 100644 (file)
@@ -399,6 +399,13 @@ void omap2_check_revision(void);
 
 /*
  * Runtime detection of OMAP3 features
+ *
+ * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip
+ *    family have OS-level control over the I/O chain clock.  This is
+ *    to avoid a window during which wakeups could potentially be lost
+ *    during powerdomain transitions.  If this bit is set, it
+ *    indicates that the chip does support OS-level control of this
+ *    feature.
  */
 extern u32 omap_features;
 
@@ -410,9 +417,10 @@ extern u32 omap_features;
 #define OMAP3_HAS_192MHZ_CLK           BIT(5)
 #define OMAP3_HAS_IO_WAKEUP            BIT(6)
 #define OMAP3_HAS_SDRC                 BIT(7)
-#define OMAP4_HAS_MPU_1GHZ             BIT(8)
-#define OMAP4_HAS_MPU_1_2GHZ           BIT(9)
-#define OMAP4_HAS_MPU_1_5GHZ           BIT(10)
+#define OMAP3_HAS_IO_CHAIN_CTRL                BIT(8)
+#define OMAP4_HAS_MPU_1GHZ             BIT(9)
+#define OMAP4_HAS_MPU_1_2GHZ           BIT(10)
+#define OMAP4_HAS_MPU_1_5GHZ           BIT(11)
 
 
 #define OMAP3_HAS_FEATURE(feat,flag)                   \
@@ -429,12 +437,11 @@ OMAP3_HAS_FEATURE(isp, ISP)
 OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
 OMAP3_HAS_FEATURE(sdrc, SDRC)
+OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL)
 
 /*
  * Runtime detection of OMAP4 features
  */
-extern u32 omap_features;
-
 #define OMAP4_HAS_FEATURE(feat, flag)                  \
 static inline unsigned int omap4_has_ ##feat(void)     \
 {                                                      \
index d11025e6e7a47df9921d252c46c64c087974132f..9418f00b6c381428fe32c61c95d8be42c455a2d4 100644 (file)
@@ -104,7 +104,7 @@ struct dmtimer_platform_data {
 
        bool loses_context;
 
-       u32 (*get_context_loss_count)(struct device *dev);
+       int (*get_context_loss_count)(struct device *dev);
 };
 
 struct omap_dm_timer *omap_dm_timer_request(void);
@@ -279,7 +279,7 @@ struct omap_dm_timer {
        struct platform_device *pdev;
        struct list_head node;
 
-       u32 (*get_context_loss_count)(struct device *dev);
+       int (*get_context_loss_count)(struct device *dev);
 };
 
 int omap_dm_timer_prepare(struct omap_dm_timer *timer);
diff --git a/arch/arm/plat-omap/include/plat/omap-alsa.h b/arch/arm/plat-omap/include/plat/omap-alsa.h
deleted file mode 100644 (file)
index b53055b..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/omap-alsa.h
- *
- * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards.
- *
- * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
- *
- * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
- * Written by Daniel Petrini, David Cohen, Anderson Briglia
- *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History
- *  -------
- *
- *  2005/07/25 INdT-10LE Kernel Team -         Alsa driver for omap osk,
- *                                     original version based in sa1100 driver
- *                                     and omap oss driver.
- */
-
-#ifndef __OMAP_ALSA_H
-#define __OMAP_ALSA_H
-
-#include <plat/dma.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <plat/mcbsp.h>
-#include <linux/platform_device.h>
-
-#define DMA_BUF_SIZE   (1024 * 8)
-
-/*
- * Buffer management for alsa and dma
- */
-struct audio_stream {
-       char *id;               /* identification string */
-       int stream_id;          /* numeric identification */
-       int dma_dev;            /* dma number of that device */
-       int *lch;               /* Chain of channels this stream is linked to */
-       char started;           /* to store if the chain was started or not */
-       int dma_q_head;         /* DMA Channel Q Head */
-       int dma_q_tail;         /* DMA Channel Q Tail */
-       char dma_q_count;       /* DMA Channel Q Count */
-       int active:1;           /* we are using this stream for transfer now */
-       int period;             /* current transfer period */
-       int periods;            /* current count of periods registerd in the DMA engine */
-       spinlock_t dma_lock;    /* for locking in DMA operations */
-       struct snd_pcm_substream *stream;       /* the pcm stream */
-       unsigned linked:1;      /* dma channels linked */
-       int offset;             /* store start position of the last period in the alsa buffer */
-       int (*hw_start)(void);  /* interface to start HW interface, e.g. McBSP */
-       int (*hw_stop)(void);   /* interface to stop HW interface, e.g. McBSP */
-};
-
-/*
- * Alsa card structure for aic23
- */
-struct snd_card_omap_codec {
-       struct snd_card *card;
-       struct snd_pcm *pcm;
-       long samplerate;
-       struct audio_stream s[2];       /* playback & capture */
-};
-
-/* Codec specific information and function pointers.
- * Codec (omap-alsa-aic23.c and omap-alsa-tsc2101.c)
- * are responsible for defining the function pointers.
- */
-struct omap_alsa_codec_config {
-       char    *name;
-       struct  omap_mcbsp_reg_cfg *mcbsp_regs_alsa;
-       struct  snd_pcm_hw_constraint_list *hw_constraints_rates;
-       struct  snd_pcm_hardware *snd_omap_alsa_playback;
-       struct  snd_pcm_hardware *snd_omap_alsa_capture;
-       void    (*codec_configure_dev)(void);
-       void    (*codec_set_samplerate)(long);
-       void    (*codec_clock_setup)(void);
-       int     (*codec_clock_on)(void);
-       int     (*codec_clock_off)(void);
-       int     (*get_default_samplerate)(void);
-};
-
-/*********** Mixer function prototypes *************************/
-int snd_omap_mixer(struct snd_card_omap_codec *);
-void snd_omap_init_mixer(void);
-
-#ifdef CONFIG_PM
-void snd_omap_suspend_mixer(void);
-void snd_omap_resume_mixer(void);
-#endif
-
-int snd_omap_alsa_post_probe(struct platform_device *pdev, struct omap_alsa_codec_config *config);
-int snd_omap_alsa_remove(struct platform_device *pdev);
-#ifdef CONFIG_PM
-int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state);
-int snd_omap_alsa_resume(struct platform_device *pdev);
-#else
-#define snd_omap_alsa_suspend  NULL
-#define snd_omap_alsa_resume   NULL
-#endif
-
-void callback_omap_alsa_sound_dma(void *);
-
-#endif
index 0840df813f4f15f4e5b0ecc1cfcd0b53269f0549..67faa7b8fe92fd932889b65d55adbe0c5a97e5de 100644 (file)
@@ -342,9 +342,9 @@ unsigned long omap_pm_cpu_get_freq(void);
  * driver must restore device context.   If the number of context losses
  * exceeds the maximum positive integer, the function will wrap to 0 and
  * continue counting.  Returns the number of context losses for this device,
- * or zero upon error.
+ * or negative value upon error.
  */
-u32 omap_pm_get_dev_context_loss_count(struct device *dev);
+int omap_pm_get_dev_context_loss_count(struct device *dev);
 
 void omap_pm_enable_off_mode(void);
 void omap_pm_disable_off_mode(void);
index 12c5b0c345bfdf93b1f6b7c83447b78f50c8454a..51423d2727a5f9b11ef886e1548905bc6a0e3ef4 100644 (file)
@@ -107,7 +107,7 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name);
 int omap_device_align_pm_lat(struct platform_device *pdev,
                             u32 new_wakeup_lat_limit);
 struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
-u32 omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_get_context_loss_count(struct platform_device *pdev);
 
 /* Other */
 
index 5419f1a2aaa432622ad377d6d56fb1438aa1b944..8b372ede17c167f90bd5b78495e4f3769d483a59 100644 (file)
@@ -600,7 +600,7 @@ int omap_hwmod_for_each_by_class(const char *classname,
                                 void *user);
 
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
index b0471bb2d47dda81c45447e381ada7ff294b502f..3dc3801aace4424c96722aa48139fc2b51197c63 100644 (file)
@@ -27,7 +27,7 @@
 #include <plat/omap_device.h>
 
 static bool off_mode_enabled;
-static u32 dummy_context_loss_counter;
+static int dummy_context_loss_counter;
 
 /*
  * Device-driver-originated constraints (via board-*.c files)
@@ -311,22 +311,32 @@ void omap_pm_disable_off_mode(void)
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       u32 count;
+       int count;
 
        if (WARN_ON(!dev))
-               return 0;
+               return -ENODEV;
 
        if (dev->parent == &omap_device_parent) {
                count = omap_device_get_context_loss_count(pdev);
        } else {
                WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
                          dev_name(dev));
-               if (off_mode_enabled)
-                       dummy_context_loss_counter++;
+
                count = dummy_context_loss_counter;
+
+               if (off_mode_enabled) {
+                       count++;
+                       /*
+                        * Context loss count has to be a non-negative value.
+                        * Clear the sign bit to get a value range from 0 to
+                        * INT_MAX.
+                        */
+                       count &= INT_MAX;
+                       dummy_context_loss_counter = count;
+               }
        }
 
        pr_debug("OMAP PM: context loss count for dev %s = %d\n",
@@ -337,7 +347,7 @@ u32 omap_pm_get_dev_context_loss_count(struct device *dev)
 
 #else
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
        return dummy_context_loss_counter;
 }
index cd90bedd9306fb6389d5f9eef0d6061db1c02076..e8d98693d2dd1fd0ac11a175510738cae8419c72 100644 (file)
@@ -78,6 +78,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/err.h>
@@ -426,7 +427,7 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
  * return the context loss counter for that hwmod, otherwise return
  * zero.
  */
-u32 omap_device_get_context_loss_count(struct platform_device *pdev)
+int omap_device_get_context_loss_count(struct platform_device *pdev)
 {
        struct omap_device *od;
        u32 ret = 0;
index 442301fe48b4176d3403de8f535837317ec7213d..c42f39f20195374bf6f0f046b487bd8e8c4511a6 100644 (file)
@@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
        struct pxa3xx_nand_timing *timing;      /* NAND Flash timing */
 };
 
+/*
+ * Current pxa3xx_nand controller has two chip select which
+ * both be workable.
+ *
+ * Notice should be taken that:
+ * When you want to use this feature, you should not enable the
+ * keep configuration feature, for two chip select could be
+ * attached with different nand chip. The different page size
+ * and timing requirement make the keep configuration impossible.
+ */
+
+/* The max num of chip select current support */
+#define NUM_CHIP_SELECT                (2)
 struct pxa3xx_nand_platform_data {
 
        /* the data flash bus is shared between the Static Memory
@@ -52,8 +65,11 @@ struct pxa3xx_nand_platform_data {
        /* allow platform code to keep OBM/bootloader defined NFC config */
        int     keep_config;
 
-       const struct mtd_partition              *parts;
-       unsigned int                            nr_parts;
+       /* indicate how many chip selects will be used */
+       int     num_cs;
+
+       const struct mtd_partition              *parts[NUM_CHIP_SELECT];
+       unsigned int                            nr_parts[NUM_CHIP_SELECT];
 
        const struct pxa3xx_nand_flash *        flash;
        size_t                                  num_flash;
index a9276667c2fb0e59c21e643aab28aef2debdee84..c7adad0e8de091ad42d021958bb1fc3b3c8cff03 100644 (file)
@@ -12,7 +12,7 @@
 */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/cpufreq.h>
index e1cbc728c7759b1e1f54923f11120b3ea4647cb2..c8bec9c7655d417ebbcb78096f16a7cbeddcf54d 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 
 #include <asm/pgtable.h>
 
index 6e3d9abc9e2e856470e304c78f31794a4f715833..93a994a5dd8f546c53ea2d80af751336d0f84184 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/errno.h>
 #include <linux/amba/pl330.h>
 #include <linux/scatterlist.h>
+#include <linux/export.h>
 
 #include <mach/dma.h>
 
index d48245bb02b3bbf6178a45e7e6ae48ad3ec8d7f6..df8155b9d4d19e550b881abf22df4dbbeab3315c 100644 (file)
@@ -24,6 +24,8 @@
 #ifndef __PLAT_GPIO_CFG_H
 #define __PLAT_GPIO_CFG_H __FILE__
 
+#include<linux/types.h>
+
 typedef unsigned int __bitwise__ samsung_gpio_pull_t;
 typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
 
index efe1d564473e02c6195774fbc47c51a23a97fad4..312b510d86b76bf0b96feba92de8aae8163380c3 100644 (file)
@@ -11,7 +11,7 @@
 */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
index dc1185dcf80d559757d289f4490723888786c2fa..c559d8438c70ee2d873afc43a7d14ee1fc2002c2 100644 (file)
@@ -11,7 +11,7 @@
  * the Free Software Foundation; either version 2 of the License.
 */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index 582333c70585222a7452a08e7684859ab554944c..78149491282749adf6c71051c1321c35c9404077 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <linux/export.h>
 
 #include <mach/dma.h>
 
index 5bdeef9698470b354dc3f144caadabda08dae00d..ccbe16f47227e2ebb171032b2a5de66289014cd0 100644 (file)
@@ -1123,5 +1123,6 @@ blissc                    MACH_BLISSC             BLISSC                  3491
 thales_adc             MACH_THALES_ADC         THALES_ADC              3492
 ubisys_p9d_evp         MACH_UBISYS_P9D_EVP     UBISYS_P9D_EVP          3493
 atdgp318               MACH_ATDGP318           ATDGP318                3494
+m28evk                 MACH_M28EVK             M28EVK                  3613
 smdk4212               MACH_SMDK4212           SMDK4212                3638
 smdk4412               MACH_SMDK4412           SMDK4412                3765
index fafed4c38fd25c18989661edcd1150b5dd3a5b4f..7c756fb189f713f3fd9d0b06de43530cb60833c1 100644 (file)
@@ -90,11 +90,6 @@ static struct mtd_partition nand_partitions[] = {
        },
 };
 
-static struct mtd_partition *nand_part_info(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(nand_partitions);
-       return nand_partitions;
-}
 
 static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
        .cle            = 21,
@@ -102,7 +97,8 @@ static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
        .rdy_pin        = GPIO_PIN_PB(28),
        .enable_pin     = GPIO_PIN_PE(23),
        .bus_width_16   = true,
-       .partition_info = nand_part_info,
+       .parts          = nand_partitions,
+       .num_parts      = ARRAY_SIZE(nand_partitions),
 };
 #endif
 
@@ -113,7 +109,7 @@ struct eth_addr {
        u8 addr[6];
 };
 static struct eth_addr __initdata hw_addr[2];
-static struct eth_platform_data __initdata eth_data[2];
+static struct macb_platform_data __initdata eth_data[2];
 
 static struct spi_board_info spi0_board_info[] __initdata = {
        {
index 6ce30fb2ec94924464a313aece641f392d6deb64..c56ddac85d615ba7acdeac3cc5fc67fa925898b3 100644 (file)
@@ -90,18 +90,13 @@ static struct mtd_partition nand_partitions[] = {
        },
 };
 
-static struct mtd_partition *nand_part_info(int size, int *num_partitions)
-{
-       *num_partitions = ARRAY_SIZE(nand_partitions);
-       return nand_partitions;
-}
-
 static struct atmel_nand_data atstk1006_nand_data __initdata = {
        .cle            = 21,
        .ale            = 22,
        .rdy_pin        = GPIO_PIN_PB(30),
        .enable_pin     = GPIO_PIN_PB(29),
-       .partition_info = nand_part_info,
+       .parts          = nand_partitions,
+       .num_parts      = ARRAY_SIZE(num_partitions),
 };
 #endif
 
@@ -110,7 +105,7 @@ struct eth_addr {
 };
 
 static struct eth_addr __initdata hw_addr[2];
-static struct eth_platform_data __initdata eth_data[2] = {
+static struct macb_platform_data __initdata eth_data[2] = {
        {
                /*
                 * The MDIO pullups on STK1000 are a bit too weak for
index 86fab77a5a00f993b8e9f82621b0cda03bdc74a2..27bd6fbe21cb5f76253ad88f50f4a12c13f9778e 100644 (file)
@@ -50,7 +50,7 @@ struct eth_addr {
        u8 addr[6];
 };
 static struct eth_addr __initdata hw_addr[1];
-static struct eth_platform_data __initdata eth_data[1] = {
+static struct macb_platform_data __initdata eth_data[1] = {
        {
                .phy_mask       = ~(1U << 1),
        },
index da14fbdd4e8e0062a87464a8c8d9d43954f63730..9d1efd1cd42534076307d59c1444a663c3b8764d 100644 (file)
@@ -102,7 +102,7 @@ struct eth_addr {
 };
 
 static struct eth_addr __initdata hw_addr[1];
-static struct eth_platform_data __initdata eth_data[1];
+static struct macb_platform_data __initdata eth_data[1];
 
 /*
  * The next two functions should go away as the boot loader is
index e61bc948f959861047449fcce267422b0fe84c78..ed137e335796e7a7e0cf881c2879037720d4200f 100644 (file)
@@ -52,7 +52,7 @@ struct eth_addr {
 };
 
 static struct eth_addr __initdata hw_addr[2];
-static struct eth_platform_data __initdata eth_data[2];
+static struct macb_platform_data __initdata eth_data[2];
 
 static int ads7846_get_pendown_state_PB26(void)
 {
index c4da5cba2dbfa718cd1a3ea34afd3a0c50257c01..05358aa5ef7d210ed42d2bb6f68be48b3fa4c690 100644 (file)
@@ -86,7 +86,7 @@ struct eth_addr {
        u8 addr[6];
 };
 static struct eth_addr __initdata hw_addr[2];
-static struct eth_platform_data __initdata eth_data[2];
+static struct macb_platform_data __initdata eth_data[2];
 
 static struct spi_eeprom eeprom_25lc010 = {
                .name = "25lc010",
index 7fbf0dcb9afe5f88e9e307f3530cdbd875cf20f1..402a7bb726696b4091e15a4e367004e634295859 100644 (file)
@@ -1067,7 +1067,7 @@ void __init at32_setup_serial_console(unsigned int usart_id)
  * -------------------------------------------------------------------- */
 
 #ifdef CONFIG_CPU_AT32AP7000
-static struct eth_platform_data macb0_data;
+static struct macb_platform_data macb0_data;
 static struct resource macb0_resource[] = {
        PBMEM(0xfff01800),
        IRQ(25),
@@ -1076,7 +1076,7 @@ DEFINE_DEV_DATA(macb, 0);
 DEV_CLK(hclk, macb0, hsb, 8);
 DEV_CLK(pclk, macb0, pbb, 6);
 
-static struct eth_platform_data macb1_data;
+static struct macb_platform_data macb1_data;
 static struct resource macb1_resource[] = {
        PBMEM(0xfff01c00),
        IRQ(26),
@@ -1086,7 +1086,7 @@ DEV_CLK(hclk, macb1, hsb, 9);
 DEV_CLK(pclk, macb1, pbb, 7);
 
 struct platform_device *__init
-at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
+at32_add_device_eth(unsigned int id, struct macb_platform_data *data)
 {
        struct platform_device *pdev;
        u32 pin_mask;
@@ -1163,7 +1163,7 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
                return NULL;
        }
 
-       memcpy(pdev->dev.platform_data, data, sizeof(struct eth_platform_data));
+       memcpy(pdev->dev.platform_data, data, sizeof(struct macb_platform_data));
        platform_device_register(pdev);
 
        return pdev;
index 679458d9a622365afd30fe371c229567dedc83cb..67b111ce332ddf02bc32afb9eacd66869a2e7a92 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/types.h>
 #include <linux/serial.h>
+#include <linux/platform_data/macb.h>
 
 #define GPIO_PIN_NONE  (-1)
 
@@ -42,12 +43,8 @@ struct atmel_uart_data {
 void at32_map_usart(unsigned int hw_id, unsigned int line, int flags);
 struct platform_device *at32_add_device_usart(unsigned int id);
 
-struct eth_platform_data {
-       u32     phy_mask;
-       u8      is_rmii;
-};
 struct platform_device *
-at32_add_device_eth(unsigned int id, struct eth_platform_data *data);
+at32_add_device_eth(unsigned int id, struct macb_platform_data *data);
 
 struct spi_board_info;
 struct platform_device *
@@ -128,7 +125,8 @@ struct atmel_nand_data {
        u8      ale;            /* address line number connected to ALE */
        u8      cle;            /* address line number connected to CLE */
        u8      bus_width_16;   /* buswidth is 16 bit */
-       struct mtd_partition *(*partition_info)(int size, int *num_partitions);
+       struct mtd_partition *parts;
+       unsigned int    num_parts;
 };
 struct platform_device *
 at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
index 7fd0ec7b5b0f2c9326d0cd4deb0f788b6fadea34..ecacdf34768b593b0e43e91c2314927cde723e83 100644 (file)
@@ -32,6 +32,8 @@ struct work_struct;
 struct bfin_serial_port {
        struct uart_port port;
        unsigned int old_status;
+       int tx_irq;
+       int rx_irq;
        int status_irq;
 #ifndef BFIN_UART_BF54X_STYLE
        unsigned int lsr;
index 1082e49f7a9f9f52fcdfbf1b8d3dfb7fdbe2a773..d1c0c0cff3efdb2f68b91edb6a6ad892f10d0a33 100644 (file)
@@ -372,9 +372,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -415,9 +420,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 55c12790881529952405cba9bd2be1a120445e4e..5470bf89e52e1147dcfcec19542dd18d2df7716d 100644 (file)
@@ -308,9 +308,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -351,9 +356,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 8d65d476f118649fb5ed75bd2067e16f1d6e1ba9..5bc6938157ad831638ca4661cb61b68c18339e36 100644 (file)
@@ -380,9 +380,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -423,9 +428,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 6410fc1af8ede5b1df46a49d960272c8661a4de8..cd289698b4dd73575682260b10ba615bf35bb71e 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -538,9 +539,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -581,9 +587,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -801,7 +812,6 @@ static struct platform_device bfin_sport1_uart_device = {
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
-#include <linux/export.h>
 
 static struct gpio_keys_button bfin_gpio_keys_table[] = {
        {BTN_0, GPIO_PF14, 1, "gpio-keys: BTN0"},
index 64f7278aba531970d2c66ac455184a958dea9f67..9f792eafd1ccf604c7b7177d3b5766e691b0c4e2 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -416,9 +417,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -459,9 +465,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -674,7 +685,6 @@ static struct platform_device bfin_sport1_uart_device = {
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
-#include <linux/export.h>
 
 static struct gpio_keys_button bfin_gpio_keys_table[] = {
        {BTN_0, GPIO_PG0, 1, "gpio-keys: BTN0"},
index e4c6a122b66cd8e595cfe50e4230ddfa9807c5bf..3ecafff5d2ef753416692b623324e800e0925437 100644 (file)
@@ -710,9 +710,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -753,9 +758,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 76dbc03a8d4d4c71e7a5ca22e17ec31da03da87c..3a92c4318d2deaa392b2cef5693b4dd46f67170a 100644 (file)
@@ -495,9 +495,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -539,9 +544,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 5da5787fc4efa8a091b3b67663d91ccbeffd9251..47cadd316e764484ac9e728d84ccfead6ee5b53f 100644 (file)
@@ -237,9 +237,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index b0ec825fb4eca73067c0ab12180406442bd61ab6..18817d57c7a15b5cf0e36bc806ef2752e91746fe 100644 (file)
@@ -192,9 +192,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 14f54a31e74c98977d488f69a6812c1c54a7bc2f..2c8f30ef6a7b2ab4b749c337814010cd9dc2fe10 100644 (file)
@@ -220,9 +220,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index ecd2801f050d9a9e0acde1e22fb6e6746edda3ba..144556e14499e6fc0a7141b8d368cd29650b5b15 100644 (file)
@@ -291,9 +291,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index fbee77fa9211a34179ae0cf5fe55bba4323af699..b597d4e50d58e74e7c29e4fd2b37658bbd12ec49 100644 (file)
@@ -150,9 +150,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 964a8e5f79b43e6e3b5ec397a5d2d4b8aed82b2b..2afd02e14bd1f317b053f0296b35161d4b71d4d3 100644 (file)
@@ -297,9 +297,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 1471c51ea6970a1e519b3cbc44f616cf95eb725c..604a430038e153c73360987a5e763ee7a4af38dc 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
@@ -304,9 +305,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -365,9 +371,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -569,7 +580,6 @@ static struct platform_device bfin_sport1_uart_device = {
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
-#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_MII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
index 47cf37de33ba67025d318f7cc998f97d0e15e83c..d916b46a44fe9334bf49fb51b940aa2889c3245a 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -305,9 +306,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -348,9 +354,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -534,7 +545,6 @@ static struct platform_device bfin_sport1_uart_device = {
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
-#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_MII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
index 33e69e427e985670200a01034c5312df8373515c..5f307228be63b7b78108c9fcc19136b01e636bf1 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -49,7 +50,6 @@ static struct platform_device rtc_device = {
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
-#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_RMII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
@@ -236,9 +236,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -280,9 +285,14 @@ static struct resource bfin_uart1_resources[] = {
                .end   = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end   = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end   = IRQ_UART1_RX+1,
+               .end   = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index c62f9dccd9f797e4ea74d8253781f478a963e186..3901dd093b9044fad71e1a7da5480273677db7cf 100644 (file)
@@ -239,9 +239,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -282,9 +287,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 3099e91114fc41048a4a795c10c3b4159b66aed7..aebd31c845f008995c90424a5b053767a3058c78 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -308,9 +309,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -351,9 +357,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 27f955db99762ee084aead94c0784d1e23554d18..7fbb0bbf86762c3fd40336cb765c1f746b90cab6 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -1565,9 +1566,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -1620,9 +1626,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -1992,7 +2003,6 @@ static struct adp8870_backlight_platform_data adp8870_pdata = {
 
 #if defined(CONFIG_BACKLIGHT_ADP8860) || defined(CONFIG_BACKLIGHT_ADP8860_MODULE)
 #include <linux/i2c/adp8860.h>
-#include <linux/export.h>
 static struct led_info adp8860_leds[] = {
        {
                .name = "adp8860-led7",
index 841803038d6fd3ff7ca1854df135be28a20fb365..6917ce2fa55ef4f61568263462e05c1cd733aa18 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -305,9 +306,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -348,9 +354,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -536,7 +547,6 @@ static struct platform_device bfin_sport1_uart_device = {
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
-#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_MII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
index 629f3c3334158b57ff8250468613eaae26ddf894..8356eb599f1937cb37b552c36a91c70bf0c0b4b9 100644 (file)
@@ -48,9 +48,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -103,9 +108,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -146,9 +156,14 @@ static struct resource bfin_uart2_resources[] = {
                .end = UART2_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART2_TX,
+               .end = IRQ_UART2_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART2_RX,
-               .end = IRQ_UART2_RX+1,
+               .end = IRQ_UART2_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 212b9e0a08c8230f7ba0c28ad349839d89dd6bd5..0350eacec21b96785f2eda1cc933cca52bbde572 100644 (file)
@@ -134,9 +134,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -177,9 +182,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -236,9 +246,14 @@ static struct resource bfin_uart2_resources[] = {
                .end = UART2_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART2_TX,
+               .end = IRQ_UART2_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART2_RX,
-               .end = IRQ_UART2_RX+1,
+               .end = IRQ_UART2_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -279,9 +294,14 @@ static struct resource bfin_uart3_resources[] = {
                .end = UART3_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART3_TX,
+               .end = IRQ_UART3_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART3_RX,
-               .end = IRQ_UART3_RX+1,
+               .end = IRQ_UART3_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index cd9cbb68de692d1243d1c11dbb54f1d0e7bfa379..bb868ac0fe2dbdf5063034be857f5ece7a9c82a4 100644 (file)
@@ -240,9 +240,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -283,9 +288,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -342,9 +352,14 @@ static struct resource bfin_uart2_resources[] = {
                .end = UART2_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART2_TX,
+               .end = IRQ_UART2_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART2_RX,
-               .end = IRQ_UART2_RX+1,
+               .end = IRQ_UART2_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -385,9 +400,14 @@ static struct resource bfin_uart3_resources[] = {
                .end = UART3_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART3_TX,
+               .end = IRQ_UART3_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART3_RX,
-               .end = IRQ_UART3_RX+1,
+               .end = IRQ_UART3_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 972e1347c6bc518865463a8313d32b725ee49241..b1b7339b6ba776a321d0614c091fe035508d63b7 100644 (file)
@@ -202,9 +202,14 @@ static struct resource bfin_uart0_resources[] = {
         .end = BFIN_UART_GCTL + 2,
         .flags = IORESOURCE_MEM,
         },
+       {
+        .start = IRQ_UART_TX,
+        .end = IRQ_UART_TX,
+        .flags = IORESOURCE_IRQ,
+        },
        {
         .start = IRQ_UART_RX,
-        .end = IRQ_UART_RX + 1,
+        .end = IRQ_UART_RX,
         .flags = IORESOURCE_IRQ,
         },
        {
index c1b72f2d635476ccc18d91f2d8455efe4d86ddb5..c017cf07ed4e2960f032f9d8b0c81a0a60e657de 100644 (file)
@@ -276,9 +276,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART_TX,
+               .end = IRQ_UART_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART_RX,
-               .end = IRQ_UART_RX+1,
+               .end = IRQ_UART_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 9490dc800ca589f6ef3f4337174bf257221f180a..27f22ed381d99767b0bda919964fed021f7d3cb5 100644 (file)
@@ -171,9 +171,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART_TX,
+               .end = IRQ_UART_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART_RX,
-               .end = IRQ_UART_RX+1,
+               .end = IRQ_UART_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index bb056e60f6edeb06b95e923e6bacd79590655662..1a57bc986aad154d2984798548b7a5878f9aaa67 100644 (file)
@@ -50,9 +50,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART_TX,
+               .end = IRQ_UART_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART_RX,
-               .end = IRQ_UART_RX+1,
+               .end = IRQ_UART_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 32d90867a9841098177b1fd5969af784ef88ac19..5f2cdb3e428cd979601b6b15d5e04a24042c7a8e 100644 (file)
@@ -3,7 +3,7 @@ if ETRAX_ARCH_V10
 config ETRAX_ETHERNET
        bool "Ethernet support"
        depends on ETRAX_ARCH_V10
-       select NET_ETHERNET
+       select ETHERNET
        select NET_CORE
        select MII
        help
index e47e9c3401b08bbbde729c13e626b9a91823ec18..de43aadcdbc47963cdaa63e0e522cdc171e3d432 100644 (file)
@@ -3,7 +3,7 @@ if ETRAX_ARCH_V32
 config ETRAX_ETHERNET
        bool "Ethernet support"
        depends on ETRAX_ARCH_V32
-       select NET_ETHERNET
+       select ETHERNET
        select NET_CORE
        select MII
        help
index f58f2c1c529526f0521448dcbe53eda6c795085e..7fb52128ddc900ebfba2952654798ab04d8e5b97 100644 (file)
@@ -163,7 +163,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
        this->ecc.mode = NAND_ECC_SOFT;
 
        /* Enable the following for a flash based bad block table */
-       /* this->options = NAND_USE_FLASH_BBT; */
+       /* this->bbt_options = NAND_BBT_USE_FLASH; */
 
        /* Scan to find existence of the device */
        if (nand_scan(crisv32_mtd, 1)) {
index d5b0cc9f976bbf15637679dbedd78f4cd57d8fc2..e03238454b0ee541e0daa556493039cedf776dbc 100644 (file)
@@ -154,7 +154,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
        this->ecc.mode = NAND_ECC_SOFT;
 
        /* Enable the following for a flash based bad block table */
-       /* this->options = NAND_USE_FLASH_BBT; */
+       /* this->bbt_options = NAND_BBT_USE_FLASH; */
 
        /* Scan to find existence of the device */
        if (nand_scan(crisv32_mtd, 1)) {
index 6c28582fb98f5559a39c3a0122104c561d4fa573..361d54019bb0bcafaed6e7e6d408d638ae4cd5c5 100644 (file)
@@ -4,8 +4,8 @@ config M68K
        select HAVE_IDE
        select HAVE_AOUT if MMU
        select GENERIC_ATOMIC64 if MMU
-       select HAVE_GENERIC_HARDIRQS if !MMU
-       select GENERIC_IRQ_SHOW if !MMU
+       select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_SHOW
        select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
 
 config RWSEM_GENERIC_SPINLOCK
index 8294f0c1785ed92d5bec8911267d0f94683eea6b..3adb499584fb40d75d79d7ab6bc83defa082d7b8 100644 (file)
@@ -2,6 +2,15 @@ if MMU
 
 comment "Bus Support"
 
+config DIO
+       bool "DIO bus support"
+       depends on HP300
+       default y
+       help
+         Say Y here to enable support for the "DIO" expansion bus used in
+         HP300 machines. If you are using such a system you almost certainly
+         want this.
+
 config NUBUS
        bool
        depends on MAC
index d214034be6a6ab6e1fc9d832eab2d995f0d7baf0..6033f5d4e67e50a4b993cbdf9d0bb85cdd5cbba9 100644 (file)
@@ -24,6 +24,37 @@ config PROC_HARDWARE
          including the model, CPU, MMU, clock speed, BogoMIPS rating,
          and memory size.
 
+config NATFEAT
+       bool "ARAnyM emulator support"
+       depends on ATARI
+       help
+         This option enables support for ARAnyM native features, such as
+         access to a disk image as /dev/hda.
+
+config NFBLOCK
+       tristate "NatFeat block device support"
+       depends on BLOCK && NATFEAT
+       help
+         Say Y to include support for the ARAnyM NatFeat block device
+         which allows direct access to the hard drives without using
+         the hardware emulation.
+
+config NFCON
+       tristate "NatFeat console driver"
+       depends on NATFEAT
+       help
+         Say Y to include support for the ARAnyM NatFeat console driver
+         which allows the console output to be redirected to the stderr
+         output of ARAnyM.
+
+config NFETH
+       tristate "NatFeat Ethernet support"
+       depends on ETHERNET && NATFEAT
+       help
+         Say Y to include support for the ARAnyM NatFeat network device
+         which will emulate a regular ethernet device while presenting an
+         ethertap device to the host system.
+
 endmenu
 
 menu "Character devices"
index c5b5212cc3f91544f42b27f73323f9cf0a9bfc42..47b5f90002abe3c69bbc66ffee7a82f5cee4f6cb 100644 (file)
@@ -1,43 +1,15 @@
 /*
- * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
+ * Amiga Linux interrupt handling code
  *
  * 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.
- *
- * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
- *           this sources where it makes sense (VERTB/PORTS/EXTER) and you must
- *           be careful that dev_id for this sources is unique since this the
- *           only possibility to distinguish between different handlers for
- *           free_irq. irq lists also have different irq flags:
- *           - IRQ_FLG_FAST: handler is inserted at top of list (after other
- *                           fast handlers)
- *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
- *                           they're executed irq level is set to the previous
- *                           one, but handlers don't need to be reentrant, if
- *                           reentrance occurred, slow handlers will be just
- *                           called again.
- *           The whole interrupt handling for CIAs is moved to cia.c
- *           /Roman Zippel
- *
- * 07/08/99: rewamp of the interrupt handling - we now have two types of
- *           interrupts, normal and fast handlers, fast handlers being
- *           marked with IRQF_DISABLED and runs with all other interrupts
- *           disabled. Normal interrupts disable their own source but
- *           run with all other interrupt sources enabled.
- *           PORTS and EXTER interrupts are always shared even if the
- *           drivers do not explicitly mark this when calling
- *           request_irq which they really should do.
- *           This is similar to the way interrupts are handled on all
- *           other architectures and makes a ton of sense besides
- *           having the advantage of making it easier to share
- *           drivers.
- *           /Jes
  */
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/amigaints.h>
 #include <asm/amipcmcia.h>
 
-static void amiga_enable_irq(unsigned int irq);
-static void amiga_disable_irq(unsigned int irq);
-static irqreturn_t ami_int1(int irq, void *dev_id);
-static irqreturn_t ami_int3(int irq, void *dev_id);
-static irqreturn_t ami_int4(int irq, void *dev_id);
-static irqreturn_t ami_int5(int irq, void *dev_id);
-
-static struct irq_controller amiga_irq_controller = {
-       .name           = "amiga",
-       .lock           = __SPIN_LOCK_UNLOCKED(amiga_irq_controller.lock),
-       .enable         = amiga_enable_irq,
-       .disable        = amiga_disable_irq,
-};
-
-/*
- * void amiga_init_IRQ(void)
- *
- * Parameters: None
- *
- * Returns:    Nothing
- *
- * This function should be called during kernel startup to initialize
- * the amiga IRQ handling routines.
- */
-
-void __init amiga_init_IRQ(void)
-{
-       if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
-               pr_err("Couldn't register int%d\n", 1);
-       if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
-               pr_err("Couldn't register int%d\n", 3);
-       if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
-               pr_err("Couldn't register int%d\n", 4);
-       if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
-               pr_err("Couldn't register int%d\n", 5);
-
-       m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
-
-       /* turn off PCMCIA interrupts */
-       if (AMIGAHW_PRESENT(PCMCIA))
-               gayle.inten = GAYLE_IRQ_IDE;
-
-       /* turn off all interrupts and enable the master interrupt bit */
-       amiga_custom.intena = 0x7fff;
-       amiga_custom.intreq = 0x7fff;
-       amiga_custom.intena = IF_SETCLR | IF_INTEN;
-
-       cia_init_IRQ(&ciaa_base);
-       cia_init_IRQ(&ciab_base);
-}
 
 /*
  * Enable/disable a particular machine specific interrupt source.
@@ -103,112 +25,150 @@ void __init amiga_init_IRQ(void)
  * internal data, that may not be changed by the interrupt at the same time.
  */
 
-static void amiga_enable_irq(unsigned int irq)
+static void amiga_irq_enable(struct irq_data *data)
 {
-       amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER));
+       amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
 }
 
-static void amiga_disable_irq(unsigned int irq)
+static void amiga_irq_disable(struct irq_data *data)
 {
-       amiga_custom.intena = 1 << (irq - IRQ_USER);
+       amiga_custom.intena = 1 << (data->irq - IRQ_USER);
 }
 
+static struct irq_chip amiga_irq_chip = {
+       .name           = "amiga",
+       .irq_enable     = amiga_irq_enable,
+       .irq_disable    = amiga_irq_disable,
+};
+
+
 /*
  * The builtin Amiga hardware interrupt handlers.
  */
 
-static irqreturn_t ami_int1(int irq, void *dev_id)
+static void ami_int1(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
        /* if serial transmit buffer empty, interrupt */
        if (ints & IF_TBE) {
                amiga_custom.intreq = IF_TBE;
-               m68k_handle_int(IRQ_AMIGA_TBE);
+               generic_handle_irq(IRQ_AMIGA_TBE);
        }
 
        /* if floppy disk transfer complete, interrupt */
        if (ints & IF_DSKBLK) {
                amiga_custom.intreq = IF_DSKBLK;
-               m68k_handle_int(IRQ_AMIGA_DSKBLK);
+               generic_handle_irq(IRQ_AMIGA_DSKBLK);
        }
 
        /* if software interrupt set, interrupt */
        if (ints & IF_SOFT) {
                amiga_custom.intreq = IF_SOFT;
-               m68k_handle_int(IRQ_AMIGA_SOFT);
+               generic_handle_irq(IRQ_AMIGA_SOFT);
        }
-       return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int3(int irq, void *dev_id)
+static void ami_int3(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
        /* if a blitter interrupt */
        if (ints & IF_BLIT) {
                amiga_custom.intreq = IF_BLIT;
-               m68k_handle_int(IRQ_AMIGA_BLIT);
+               generic_handle_irq(IRQ_AMIGA_BLIT);
        }
 
        /* if a copper interrupt */
        if (ints & IF_COPER) {
                amiga_custom.intreq = IF_COPER;
-               m68k_handle_int(IRQ_AMIGA_COPPER);
+               generic_handle_irq(IRQ_AMIGA_COPPER);
        }
 
        /* if a vertical blank interrupt */
        if (ints & IF_VERTB) {
                amiga_custom.intreq = IF_VERTB;
-               m68k_handle_int(IRQ_AMIGA_VERTB);
+               generic_handle_irq(IRQ_AMIGA_VERTB);
        }
-       return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int4(int irq, void *dev_id)
+static void ami_int4(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
        /* if audio 0 interrupt */
        if (ints & IF_AUD0) {
                amiga_custom.intreq = IF_AUD0;
-               m68k_handle_int(IRQ_AMIGA_AUD0);
+               generic_handle_irq(IRQ_AMIGA_AUD0);
        }
 
        /* if audio 1 interrupt */
        if (ints & IF_AUD1) {
                amiga_custom.intreq = IF_AUD1;
-               m68k_handle_int(IRQ_AMIGA_AUD1);
+               generic_handle_irq(IRQ_AMIGA_AUD1);
        }
 
        /* if audio 2 interrupt */
        if (ints & IF_AUD2) {
                amiga_custom.intreq = IF_AUD2;
-               m68k_handle_int(IRQ_AMIGA_AUD2);
+               generic_handle_irq(IRQ_AMIGA_AUD2);
        }
 
        /* if audio 3 interrupt */
        if (ints & IF_AUD3) {
                amiga_custom.intreq = IF_AUD3;
-               m68k_handle_int(IRQ_AMIGA_AUD3);
+               generic_handle_irq(IRQ_AMIGA_AUD3);
        }
-       return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int5(int irq, void *dev_id)
+static void ami_int5(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
        /* if serial receive buffer full interrupt */
        if (ints & IF_RBF) {
                /* acknowledge of IF_RBF must be done by the serial interrupt */
-               m68k_handle_int(IRQ_AMIGA_RBF);
+               generic_handle_irq(IRQ_AMIGA_RBF);
        }
 
        /* if a disk sync interrupt */
        if (ints & IF_DSKSYN) {
                amiga_custom.intreq = IF_DSKSYN;
-               m68k_handle_int(IRQ_AMIGA_DSKSYN);
+               generic_handle_irq(IRQ_AMIGA_DSKSYN);
        }
-       return IRQ_HANDLED;
+}
+
+
+/*
+ * void amiga_init_IRQ(void)
+ *
+ * Parameters: None
+ *
+ * Returns:    Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the amiga IRQ handling routines.
+ */
+
+void __init amiga_init_IRQ(void)
+{
+       m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
+                                 AMI_STD_IRQS);
+
+       irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
+       irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
+       irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
+       irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
+
+       /* turn off PCMCIA interrupts */
+       if (AMIGAHW_PRESENT(PCMCIA))
+               gayle.inten = GAYLE_IRQ_IDE;
+
+       /* turn off all interrupts and enable the master interrupt bit */
+       amiga_custom.intena = 0x7fff;
+       amiga_custom.intreq = 0x7fff;
+       amiga_custom.intena = IF_SETCLR | IF_INTEN;
+
+       cia_init_IRQ(&ciaa_base);
+       cia_init_IRQ(&ciab_base);
 }
index ecd0f7ca6f0e34caca534e4dcc3a445805649741..18c0e29976e37475cf822b5b11d9bf32437791eb 100644 (file)
@@ -93,13 +93,14 @@ static irqreturn_t cia_handler(int irq, void *dev_id)
        amiga_custom.intreq = base->int_mask;
        for (; ints; mach_irq++, ints >>= 1) {
                if (ints & 1)
-                       m68k_handle_int(mach_irq);
+                       generic_handle_irq(mach_irq);
        }
        return IRQ_HANDLED;
 }
 
-static void cia_enable_irq(unsigned int irq)
+static void cia_irq_enable(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
        unsigned char mask;
 
        if (irq >= IRQ_AMIGA_CIAB) {
@@ -113,19 +114,20 @@ static void cia_enable_irq(unsigned int irq)
        }
 }
 
-static void cia_disable_irq(unsigned int irq)
+static void cia_irq_disable(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        if (irq >= IRQ_AMIGA_CIAB)
                cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
        else
                cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
 }
 
-static struct irq_controller cia_irq_controller = {
+static struct irq_chip cia_irq_chip = {
        .name           = "cia",
-       .lock           = __SPIN_LOCK_UNLOCKED(cia_irq_controller.lock),
-       .enable         = cia_enable_irq,
-       .disable        = cia_disable_irq,
+       .irq_enable     = cia_irq_enable,
+       .irq_disable    = cia_irq_disable,
 };
 
 /*
@@ -134,9 +136,9 @@ static struct irq_controller cia_irq_controller = {
  * into this chain.
  */
 
-static void auto_enable_irq(unsigned int irq)
+static void auto_irq_enable(struct irq_data *data)
 {
-       switch (irq) {
+       switch (data->irq) {
        case IRQ_AUTO_2:
                amiga_custom.intena = IF_SETCLR | IF_PORTS;
                break;
@@ -146,9 +148,9 @@ static void auto_enable_irq(unsigned int irq)
        }
 }
 
-static void auto_disable_irq(unsigned int irq)
+static void auto_irq_disable(struct irq_data *data)
 {
-       switch (irq) {
+       switch (data->irq) {
        case IRQ_AUTO_2:
                amiga_custom.intena = IF_PORTS;
                break;
@@ -158,24 +160,25 @@ static void auto_disable_irq(unsigned int irq)
        }
 }
 
-static struct irq_controller auto_irq_controller = {
+static struct irq_chip auto_irq_chip = {
        .name           = "auto",
-       .lock           = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
-       .enable         = auto_enable_irq,
-       .disable        = auto_disable_irq,
+       .irq_enable     = auto_irq_enable,
+       .irq_disable    = auto_irq_disable,
 };
 
 void __init cia_init_IRQ(struct ciabase *base)
 {
-       m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS);
+       m68k_setup_irq_controller(&cia_irq_chip, handle_simple_irq,
+                                 base->cia_irq, CIA_IRQS);
 
        /* clear any pending interrupt and turn off all interrupts */
        cia_set_irq(base, CIA_ICR_ALL);
        cia_able_irq(base, CIA_ICR_ALL);
 
        /* override auto int and install CIA handler */
-       m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
-       m68k_irq_startup(base->handler_irq);
+       m68k_setup_irq_controller(&auto_irq_chip, handle_simple_irq,
+                                 base->handler_irq, 1);
+       m68k_irq_startup_irq(base->handler_irq);
        if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
                        base->name, base))
                pr_err("Couldn't register %s interrupt\n", base->name);
index 5d47f3aa3810fb0d5af3abab09a01156fa6b2a7f..17be1e7e2df296dae497bebb81cd45d25184bd6d 100644 (file)
@@ -1,19 +1,13 @@
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
-#include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/apollohw.h>
 
-void dn_process_int(unsigned int irq, struct pt_regs *fp)
+unsigned int apollo_irq_startup(struct irq_data *data)
 {
-       __m68k_handle_int(irq, fp);
+       unsigned int irq = data->irq;
 
-       *(volatile unsigned char *)(pica)=0x20;
-       *(volatile unsigned char *)(picb)=0x20;
-}
-
-int apollo_irq_startup(unsigned int irq)
-{
        if (irq < 8)
                *(volatile unsigned char *)(pica+1) &= ~(1 << irq);
        else
@@ -21,24 +15,33 @@ int apollo_irq_startup(unsigned int irq)
        return 0;
 }
 
-void apollo_irq_shutdown(unsigned int irq)
+void apollo_irq_shutdown(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        if (irq < 8)
                *(volatile unsigned char *)(pica+1) |= (1 << irq);
        else
                *(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
 }
 
-static struct irq_controller apollo_irq_controller = {
+void apollo_irq_eoi(struct irq_data *data)
+{
+       *(volatile unsigned char *)(pica) = 0x20;
+       *(volatile unsigned char *)(picb) = 0x20;
+}
+
+static struct irq_chip apollo_irq_chip = {
        .name           = "apollo",
-       .lock           = __SPIN_LOCK_UNLOCKED(apollo_irq_controller.lock),
-       .startup        = apollo_irq_startup,
-       .shutdown       = apollo_irq_shutdown,
+       .irq_startup    = apollo_irq_startup,
+       .irq_shutdown   = apollo_irq_shutdown,
+       .irq_eoi        = apollo_irq_eoi,
 };
 
 
 void __init dn_init_IRQ(void)
 {
-       m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int);
-       m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16);
+       m68k_setup_user_interrupt(VEC_USER + 96, 16);
+       m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq,
+                                 IRQ_APOLLO, 16);
 }
index 26a804e67bced56a5d447ae66d23ce40c3e3fd97..6d196dadfdbc3dae5edca91a509527709ea8092c 100644 (file)
  * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
  * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
  * be allocated by atari_register_vme_int().
- *
- * Each interrupt can be of three types:
- *
- *  - SLOW: The handler runs with all interrupts enabled, except the one it
- *    was called by (to avoid reentering). This should be the usual method.
- *    But it is currently possible only for MFP ints, since only the MFP
- *    offers an easy way to mask interrupts.
- *
- *  - FAST: The handler runs with all interrupts disabled. This should be used
- *    only for really fast handlers, that just do actions immediately
- *    necessary, and let the rest do a bottom half or task queue.
- *
- *  - PRIORITIZED: The handler can be interrupted by higher-level ints
- *    (greater IPL, no MFP priorities!). This is the method of choice for ints
- *    which should be slow, but are not from a MFP.
- *
- * The feature of more than one handler for one int source is still there, but
- * only applicable if all handers are of the same type. To not slow down
- * processing of ints with only one handler by the chaining feature, the list
- * calling function atari_call_irq_list() is only plugged in at the time the
- * second handler is registered.
- *
- * Implementation notes: For fast-as-possible int handling, there are separate
- * entry points for each type (slow/fast/prio). The assembler handler calls
- * the irq directly in the usual case, no C wrapper is involved. In case of
- * multiple handlers, atari_call_irq_list() is registered as handler and calls
- * in turn the real irq's. To ease access from assembler level to the irq
- * function pointer and accompanying data, these two are stored in a separate
- * array, irq_handler[]. The rest of data (type, name) are put into a second
- * array, irq_param, that is accessed from C only. For each slow interrupt (32
- * in all) there are separate handler functions, which makes it possible to
- * hard-code the MFP register address and value, are necessary to mask the
- * int. If there'd be only one generic function, lots of calculations would be
- * needed to determine MFP register and int mask from the vector number :-(
- *
- * Furthermore, slow ints may not lower the IPL below its previous value
- * (before the int happened). This is needed so that an int of class PRIO, on
- * that this int may be stacked, cannot be reentered. This feature is
- * implemented as follows: If the stack frame format is 1 (throwaway), the int
- * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
- * 2, which still blocks the HSYNC, but no interrupts of interest. If the
- * frame format is 0, the int is nested, and the old IPL value can be found in
- * the sr copy in the frame.
- */
-
-#if 0
-
-#define        NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES)
-
-typedef void (*asm_irq_handler)(void);
-
-struct irqhandler {
-       irqreturn_t (*handler)(int, void *, struct pt_regs *);
-       void    *dev_id;
-};
-
-struct irqparam {
-       unsigned long   flags;
-       const char      *devname;
-};
-
-/*
- * Array with irq's and their parameter data. This array is accessed from low
- * level assembler code, so an element size of 8 allows usage of index scaling
- * addressing mode.
  */
-static struct irqhandler irq_handler[NUM_INT_SOURCES];
-
-/*
- * This array hold the rest of parameters of int handlers: type
- * (slow,fast,prio) and the name of the handler. These values are only
- * accessed from C
- */
-static struct irqparam irq_param[NUM_INT_SOURCES];
-
-/* check for valid int number (complex, sigh...) */
-#define        IS_VALID_INTNO(n)                                                                                       \
-       ((n) > 0 &&                                                                                                             \
-        /* autovec and ST-MFP ok anyway */                                                             \
-        (((n) < TTMFP_SOURCE_BASE) ||                                                                  \
-         /* TT-MFP ok if present */                                                                    \
-         ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE &&                 \
-          ATARIHW_PRESENT(TT_MFP)) ||                                                                  \
-         /* SCC ok if present and number even */                                               \
-         ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE &&                   \
-          !((n) & 1) && ATARIHW_PRESENT(SCC)) ||                                               \
-         /* greater numbers ok if they are registered VME vectors */           \
-         ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
-                 free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
-
-
-/*
- * Here start the assembler entry points for interrupts
- */
-
-#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
-
-#define        BUILD_SLOW_IRQ(n)                                                  \
-asmlinkage void IRQ_NAME(n);                                              \
-/* Dummy function to allow asm with operands.  */                         \
-void atari_slow_irq_##n##_dummy (void) {                                  \
-__asm__ (__ALIGN_STR "\n"                                                 \
-"atari_slow_irq_" #n "_handler:\t"                                        \
-"      addl    %6,%5\n"        /* preempt_count() += HARDIRQ_OFFSET */    \
-       SAVE_ALL_INT "\n"                                                  \
-       GET_CURRENT(%%d0) "\n"                                             \
-"      andb    #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */          \
-       /* get old IPL from stack frame */                                 \
-"      bfextu  %%sp@(%c2){#5,#3},%%d0\n"                                  \
-"      movew   %%sr,%%d1\n"                                               \
-"      bfins   %%d0,%%d1{#21,#3}\n"                                       \
-"      movew   %%d1,%%sr\n"            /* set IPL = previous value */     \
-"      addql   #1,%a0\n"                                                  \
-"      lea     %a1,%%a0\n"                                                \
-"      pea     %%sp@\n"                /* push addr of frame */           \
-"      movel   %%a0@(4),%%sp@-\n"      /* push handler data */            \
-"      pea     (%c3+8)\n"              /* push int number */              \
-"      movel   %%a0@,%%a0\n"                                              \
-"      jbsr    %%a0@\n"                /* call the handler */             \
-"      addql   #8,%%sp\n"                                                 \
-"      addql   #4,%%sp\n"                                                 \
-"      orw     #0x0600,%%sr\n"                                            \
-"      andw    #0xfeff,%%sr\n"         /* set IPL = 6 again */            \
-"      orb     #(1<<(%c3&7)),%a4:w\n"  /* now unmask the int again */     \
-"      jbra    ret_from_interrupt\n"                                      \
-        : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]),       \
-            "n" (PT_OFF_SR), "n" (n),                                     \
-            "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a)   \
-                       : (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \
-            "m" (preempt_count()), "di" (HARDIRQ_OFFSET)                  \
-);                                                                        \
-       for (;;);                       /* fake noreturn */                \
-}
-
-BUILD_SLOW_IRQ(0);
-BUILD_SLOW_IRQ(1);
-BUILD_SLOW_IRQ(2);
-BUILD_SLOW_IRQ(3);
-BUILD_SLOW_IRQ(4);
-BUILD_SLOW_IRQ(5);
-BUILD_SLOW_IRQ(6);
-BUILD_SLOW_IRQ(7);
-BUILD_SLOW_IRQ(8);
-BUILD_SLOW_IRQ(9);
-BUILD_SLOW_IRQ(10);
-BUILD_SLOW_IRQ(11);
-BUILD_SLOW_IRQ(12);
-BUILD_SLOW_IRQ(13);
-BUILD_SLOW_IRQ(14);
-BUILD_SLOW_IRQ(15);
-BUILD_SLOW_IRQ(16);
-BUILD_SLOW_IRQ(17);
-BUILD_SLOW_IRQ(18);
-BUILD_SLOW_IRQ(19);
-BUILD_SLOW_IRQ(20);
-BUILD_SLOW_IRQ(21);
-BUILD_SLOW_IRQ(22);
-BUILD_SLOW_IRQ(23);
-BUILD_SLOW_IRQ(24);
-BUILD_SLOW_IRQ(25);
-BUILD_SLOW_IRQ(26);
-BUILD_SLOW_IRQ(27);
-BUILD_SLOW_IRQ(28);
-BUILD_SLOW_IRQ(29);
-BUILD_SLOW_IRQ(30);
-BUILD_SLOW_IRQ(31);
-
-asm_irq_handler slow_handlers[32] = {
-       [0]     = atari_slow_irq_0_handler,
-       [1]     = atari_slow_irq_1_handler,
-       [2]     = atari_slow_irq_2_handler,
-       [3]     = atari_slow_irq_3_handler,
-       [4]     = atari_slow_irq_4_handler,
-       [5]     = atari_slow_irq_5_handler,
-       [6]     = atari_slow_irq_6_handler,
-       [7]     = atari_slow_irq_7_handler,
-       [8]     = atari_slow_irq_8_handler,
-       [9]     = atari_slow_irq_9_handler,
-       [10]    = atari_slow_irq_10_handler,
-       [11]    = atari_slow_irq_11_handler,
-       [12]    = atari_slow_irq_12_handler,
-       [13]    = atari_slow_irq_13_handler,
-       [14]    = atari_slow_irq_14_handler,
-       [15]    = atari_slow_irq_15_handler,
-       [16]    = atari_slow_irq_16_handler,
-       [17]    = atari_slow_irq_17_handler,
-       [18]    = atari_slow_irq_18_handler,
-       [19]    = atari_slow_irq_19_handler,
-       [20]    = atari_slow_irq_20_handler,
-       [21]    = atari_slow_irq_21_handler,
-       [22]    = atari_slow_irq_22_handler,
-       [23]    = atari_slow_irq_23_handler,
-       [24]    = atari_slow_irq_24_handler,
-       [25]    = atari_slow_irq_25_handler,
-       [26]    = atari_slow_irq_26_handler,
-       [27]    = atari_slow_irq_27_handler,
-       [28]    = atari_slow_irq_28_handler,
-       [29]    = atari_slow_irq_29_handler,
-       [30]    = atari_slow_irq_30_handler,
-       [31]    = atari_slow_irq_31_handler
-};
-
-asmlinkage void atari_fast_irq_handler( void );
-asmlinkage void atari_prio_irq_handler( void );
-
-/* Dummy function to allow asm with operands.  */
-void atari_fast_prio_irq_dummy (void) {
-__asm__ (__ALIGN_STR "\n"
-"atari_fast_irq_handler:\n\t"
-       "orw    #0x700,%%sr\n"          /* disable all interrupts */
-"atari_prio_irq_handler:\n\t"
-       "addl   %3,%2\n\t"              /* preempt_count() += HARDIRQ_OFFSET */
-       SAVE_ALL_INT "\n\t"
-       GET_CURRENT(%%d0) "\n\t"
-       /* get vector number from stack frame and convert to source */
-       "bfextu %%sp@(%c1){#4,#10},%%d0\n\t"
-       "subw   #(0x40-8),%%d0\n\t"
-       "jpl    1f\n\t"
-       "addw   #(0x40-8-0x18),%%d0\n"
-    "1:\tlea   %a0,%%a0\n\t"
-       "addql  #1,%%a0@(%%d0:l:4)\n\t"
-       "lea    irq_handler,%%a0\n\t"
-       "lea    %%a0@(%%d0:l:8),%%a0\n\t"
-       "pea    %%sp@\n\t"              /* push frame address */
-       "movel  %%a0@(4),%%sp@-\n\t"    /* push handler data */
-       "movel  %%d0,%%sp@-\n\t"        /* push int number */
-       "movel  %%a0@,%%a0\n\t"
-       "jsr    %%a0@\n\t"              /* and call the handler */
-       "addql  #8,%%sp\n\t"
-       "addql  #4,%%sp\n\t"
-       "jbra   ret_from_interrupt"
-        : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
-            "m" (preempt_count()), "di" (HARDIRQ_OFFSET)
-);
-       for (;;);
-}
-#endif
 
 /*
  * Bitmap for free interrupt vector numbers
@@ -320,31 +84,44 @@ extern void atari_microwire_cmd(int cmd);
 
 extern int atari_SCC_reset_done;
 
-static int atari_startup_irq(unsigned int irq)
+static unsigned int atari_irq_startup(struct irq_data *data)
 {
-       m68k_irq_startup(irq);
+       unsigned int irq = data->irq;
+
+       m68k_irq_startup(data);
        atari_turnon_irq(irq);
        atari_enable_irq(irq);
        return 0;
 }
 
-static void atari_shutdown_irq(unsigned int irq)
+static void atari_irq_shutdown(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        atari_disable_irq(irq);
        atari_turnoff_irq(irq);
-       m68k_irq_shutdown(irq);
+       m68k_irq_shutdown(data);
 
        if (irq == IRQ_AUTO_4)
            vectors[VEC_INT4] = falcon_hblhandler;
 }
 
-static struct irq_controller atari_irq_controller = {
+static void atari_irq_enable(struct irq_data *data)
+{
+       atari_enable_irq(data->irq);
+}
+
+static void atari_irq_disable(struct irq_data *data)
+{
+       atari_disable_irq(data->irq);
+}
+
+static struct irq_chip atari_irq_chip = {
        .name           = "atari",
-       .lock           = __SPIN_LOCK_UNLOCKED(atari_irq_controller.lock),
-       .startup        = atari_startup_irq,
-       .shutdown       = atari_shutdown_irq,
-       .enable         = atari_enable_irq,
-       .disable        = atari_disable_irq,
+       .irq_startup    = atari_irq_startup,
+       .irq_shutdown   = atari_irq_shutdown,
+       .irq_enable     = atari_irq_enable,
+       .irq_disable    = atari_irq_disable,
 };
 
 /*
@@ -360,8 +137,9 @@ static struct irq_controller atari_irq_controller = {
 
 void __init atari_init_IRQ(void)
 {
-       m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL);
-       m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
+       m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER);
+       m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1,
+                                 NUM_ATARI_SOURCES - 1);
 
        /* Initialize the MFP(s) */
 
index 1edd95095cb4f6c9b1bc59a6fd219693f19454e6..81286476f7403c1a273350d686ea32d65f0b7533 100644 (file)
@@ -86,7 +86,7 @@ static void bvme6000_get_model(char *model)
  */
 static void __init bvme6000_init_IRQ(void)
 {
-       m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+       m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 void __init config_bvme6000(void)
index f6312c7d87276a1c2e4b23005874a0b247689c8a..c87fe69b0728bdccab9d2081c2ed6be95be16dca 100644 (file)
@@ -70,7 +70,7 @@ void __init hp300_sched_init(irq_handler_t vector)
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
+  if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector))
     pr_err("Couldn't register timer interrupt\n");
 
   out_8(CLOCKBASE + CLKCR2, 0x1);              /* select CR1 */
index 870e5347155b373a386fd1a8a13c47c43395cd51..db30ed276878dcbf793e667d6edb279c5234a60a 100644 (file)
 
 #ifdef CONFIG_MMU
 
+static inline void ack_bad_irq(unsigned int irq)
+{
+       pr_crit("unexpected IRQ trap at vector %02x\n", irq);
+}
+
 /* entry.S is sensitive to the offsets of these fields */
 typedef struct {
        unsigned int __softirq_pending;
index 69ed0d74d5327a8af398b061daf5184649fd3862..6198df5ff245346971e3b947944591c50955a8ab 100644 (file)
 
 #ifdef CONFIG_MMU
 
-#include <linux/linkage.h>
-#include <linux/hardirq.h>
-#include <linux/irqreturn.h>
-#include <linux/spinlock_types.h>
-
 /*
  * Interrupt source definitions
  * General interrupt sources are the level 1-7.
 
 #define IRQ_USER       8
 
-extern unsigned int irq_canonicalize(unsigned int irq);
-
-struct pt_regs;
-
 /*
  * various flags for request_irq() - the Amiga now uses the standard
  * mechanism like all other architectures - IRQF_DISABLED and
@@ -71,57 +62,27 @@ struct pt_regs;
 #define IRQ_FLG_STD    (0x8000)        /* internally used              */
 #endif
 
-/*
- * This structure is used to chain together the ISRs for a particular
- * interrupt source (if it supports chaining).
- */
-typedef struct irq_node {
-       irqreturn_t     (*handler)(int, void *);
-       void            *dev_id;
-       struct irq_node *next;
-       unsigned long   flags;
-       const char      *devname;
-} irq_node_t;
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-struct irq_handler {
-       int             (*handler)(int, void *);
-       unsigned long   flags;
-       void            *dev_id;
-       const char      *devname;
-};
-
-struct irq_controller {
-       const char *name;
-       spinlock_t lock;
-       int (*startup)(unsigned int irq);
-       void (*shutdown)(unsigned int irq);
-       void (*enable)(unsigned int irq);
-       void (*disable)(unsigned int irq);
-};
-
-extern int m68k_irq_startup(unsigned int);
-extern void m68k_irq_shutdown(unsigned int);
-
-/*
- * This function returns a new irq_node_t
- */
-extern irq_node_t *new_irq_node(void);
+struct irq_data;
+struct irq_chip;
+struct irq_desc;
+extern unsigned int m68k_irq_startup(struct irq_data *data);
+extern unsigned int m68k_irq_startup_irq(unsigned int irq);
+extern void m68k_irq_shutdown(struct irq_data *data);
+extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int,
+                                                     struct pt_regs *));
+extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt);
+extern void m68k_setup_irq_controller(struct irq_chip *,
+                                     void (*handle)(unsigned int irq,
+                                                    struct irq_desc *desc),
+                                     unsigned int irq, unsigned int cnt);
 
-extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-                                     void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
-
-asmlinkage void m68k_handle_int(unsigned int);
-asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
+extern unsigned int irq_canonicalize(unsigned int irq);
 
 #else
 #define irq_canonicalize(irq)  (irq)
 #endif /* CONFIG_MMU */
 
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+extern atomic_t irq_err_count;
 
 #endif /* _M68K_IRQ_H_ */
index c2a1c5eac1a636367b0b59437fe478ae2d4a0aca..12ebe43b008b511839eb5825e08ee16d3fb7adaf 100644 (file)
@@ -12,6 +12,8 @@ extern void mac_reset(void);
 extern void mac_poweroff(void);
 extern void mac_init_IRQ(void);
 extern int mac_irq_pending(unsigned int);
+extern void mac_irq_enable(struct irq_data *data);
+extern void mac_irq_disable(struct irq_data *data);
 
 /*
  *     Floppy driver magic hook - probably shouldn't be here
index 3d970afb708fc5bd19937cef0afefea56e8279db..22f12c9eb910d62f4d693e9a26f9f01696670034 100644 (file)
@@ -24,6 +24,3 @@
 #define Q40_IRQ10_MASK       (1<<5)
 #define Q40_IRQ14_MASK       (1<<6)
 #define Q40_IRQ15_MASK       (1<<7)
-
-extern unsigned long q40_probe_irq_on (void);
-extern int q40_probe_irq_off (unsigned long irqs);
index e7f0f2e5ad4478a767732c70f229b78aca753383..c5696193281a16a405be19906d649091c273de42 100644 (file)
@@ -6,16 +6,15 @@ extra-$(CONFIG_MMU)   := head.o
 extra-$(CONFIG_SUN3)   := sun3-head.o
 extra-y                        += vmlinux.lds
 
-obj-y  := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \
-          sys_m68k.o syscalltable.o time.o traps.o
+obj-y  := entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o setup.o \
+          signal.o sys_m68k.o syscalltable.o time.o traps.o
 
-obj-$(CONFIG_MMU)      += ints.o devres.o vectors.o
-devres-$(CONFIG_MMU)   = ../../../kernel/irq/devres.o
+obj-$(CONFIG_MMU)      += ints.o vectors.o
 
 ifndef CONFIG_MMU_SUN3
 obj-y                  += dma.o
 endif
 ifndef CONFIG_MMU
-obj-y                  += init_task.o irq.o
+obj-y                  += init_task.o
 endif
 
index bd0ec05263b2f3bc047c8008a5453e7cd98ceb31..c713f514843dbbea4ef6b42dcbec445e53847def 100644 (file)
@@ -48,7 +48,7 @@
 .globl sys_fork, sys_clone, sys_vfork
 .globl ret_from_interrupt, bad_interrupt
 .globl auto_irqhandler_fixup
-.globl user_irqvec_fixup, user_irqhandler_fixup
+.globl user_irqvec_fixup
 
 .text
 ENTRY(buserr)
@@ -207,7 +207,7 @@ ENTRY(auto_inthandler)
        movel   %sp,%sp@-
        movel   %d0,%sp@-               |  put vector # on stack
 auto_irqhandler_fixup = . + 2
-       jsr     __m68k_handle_int       |  process the IRQ
+       jsr     do_IRQ                  |  process the IRQ
        addql   #8,%sp                  |  pop parameters off stack
 
 ret_from_interrupt:
@@ -240,8 +240,7 @@ user_irqvec_fixup = . + 2
 
        movel   %sp,%sp@-
        movel   %d0,%sp@-               |  put vector # on stack
-user_irqhandler_fixup = . + 2
-       jsr     __m68k_handle_int       |  process the IRQ
+       jsr     do_IRQ                  |  process the IRQ
        addql   #8,%sp                  |  pop parameters off stack
 
        subqb   #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
index 761ee0440c996a29d4fe784f56571e2cab3358ee..74fefac00899893add2d342726fe2d2050f88cac 100644 (file)
@@ -4,25 +4,6 @@
  * 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.
- *
- * 07/03/96: Timer initialization, and thus mach_sched_init(),
- *           removed from request_irq() and moved to init_time().
- *           We should therefore consider renaming our add_isr() and
- *           remove_isr() to request_irq() and free_irq()
- *           respectively, so they are compliant with the other
- *           architectures.                                     /Jes
- * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
- *           Removed irq list support, if any machine needs an irq server
- *           it must implement this itself (as it's already done), instead
- *           only default handler are used with mach_default_handler.
- *           request_irq got some flags different from other architectures:
- *           - IRQ_FLG_REPLACE : Replace an existing handler (the default one
- *                               can be replaced without this flag)
- *           - IRQ_FLG_LOCK : handler can't be replaced
- *           There are other machine depending flags, see there
- *           If you want to replace a default handler you should know what
- *           you're doing, since it might handle different other irq sources
- *           which must be served                               /Roman Zippel
  */
 
 #include <linux/module.h>
 #endif
 
 extern u32 auto_irqhandler_fixup[];
-extern u32 user_irqhandler_fixup[];
 extern u16 user_irqvec_fixup[];
 
-/* table for system interrupt handlers */
-static struct irq_node *irq_list[NR_IRQS];
-static struct irq_controller *irq_controller[NR_IRQS];
-static int irq_depth[NR_IRQS];
-
 static int m68k_first_user_vec;
 
-static struct irq_controller auto_irq_controller = {
+static struct irq_chip auto_irq_chip = {
        .name           = "auto",
-       .lock           = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
-       .startup        = m68k_irq_startup,
-       .shutdown       = m68k_irq_shutdown,
+       .irq_startup    = m68k_irq_startup,
+       .irq_shutdown   = m68k_irq_shutdown,
 };
 
-static struct irq_controller user_irq_controller = {
+static struct irq_chip user_irq_chip = {
        .name           = "user",
-       .lock           = __SPIN_LOCK_UNLOCKED(user_irq_controller.lock),
-       .startup        = m68k_irq_startup,
-       .shutdown       = m68k_irq_shutdown,
+       .irq_startup    = m68k_irq_startup,
+       .irq_shutdown   = m68k_irq_shutdown,
 };
 
-#define NUM_IRQ_NODES 100
-static irq_node_t nodes[NUM_IRQ_NODES];
-
 /*
  * void init_IRQ(void)
  *
@@ -96,7 +66,7 @@ void __init init_IRQ(void)
        }
 
        for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
-               irq_controller[i] = &auto_irq_controller;
+               irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);
 
        mach_init_IRQ();
 }
@@ -106,7 +76,7 @@ void __init init_IRQ(void)
  * @handler: called from auto vector interrupts
  *
  * setup the handler to be called from auto vector interrupts instead of the
- * standard __m68k_handle_int(), it will be called with irq numbers in the range
+ * standard do_IRQ(), it will be called with irq numbers in the range
  * from IRQ_AUTO_1 - IRQ_AUTO_7.
  */
 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
@@ -120,217 +90,49 @@ void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_re
  * m68k_setup_user_interrupt
  * @vec: first user vector interrupt to handle
  * @cnt: number of active user vector interrupts
- * @handler: called from user vector interrupts
  *
  * setup user vector interrupts, this includes activating the specified range
  * of interrupts, only then these interrupts can be requested (note: this is
- * different from auto vector interrupts). An optional handler can be installed
- * to be called instead of the default __m68k_handle_int(), it will be called
- * with irq numbers starting from IRQ_USER.
+ * different from auto vector interrupts).
  */
-void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-                                     void (*handler)(unsigned int, struct pt_regs *))
+void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt)
 {
        int i;
 
        BUG_ON(IRQ_USER + cnt > NR_IRQS);
        m68k_first_user_vec = vec;
        for (i = 0; i < cnt; i++)
-               irq_controller[IRQ_USER + i] = &user_irq_controller;
+               irq_set_chip(IRQ_USER + i, &user_irq_chip);
        *user_irqvec_fixup = vec - IRQ_USER;
-       if (handler)
-               *user_irqhandler_fixup = (u32)handler;
        flush_icache();
 }
 
 /**
  * m68k_setup_irq_controller
- * @contr: irq controller which controls specified irq
+ * @chip: irq chip which controls specified irq
+ * @handle: flow handler which handles specified irq
  * @irq: first irq to be managed by the controller
+ * @cnt: number of irqs to be managed by the controller
  *
  * Change the controller for the specified range of irq, which will be used to
  * manage these irq. auto/user irq already have a default controller, which can
  * be changed as well, but the controller probably should use m68k_irq_startup/
  * m68k_irq_shutdown.
  */
-void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
+void m68k_setup_irq_controller(struct irq_chip *chip,
+                              irq_flow_handler_t handle, unsigned int irq,
                               unsigned int cnt)
 {
        int i;
 
-       for (i = 0; i < cnt; i++)
-               irq_controller[irq + i] = contr;
-}
-
-irq_node_t *new_irq_node(void)
-{
-       irq_node_t *node;
-       short i;
-
-       for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
-               if (!node->handler) {
-                       memset(node, 0, sizeof(*node));
-                       return node;
-               }
+       for (i = 0; i < cnt; i++) {
+               irq_set_chip(irq + i, chip);
+               if (handle)
+                       irq_set_handler(irq + i, handle);
        }
-
-       printk ("new_irq_node: out of nodes\n");
-       return NULL;
 }
 
-int setup_irq(unsigned int irq, struct irq_node *node)
-{
-       struct irq_controller *contr;
-       struct irq_node **prev;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-               printk("%s: Incorrect IRQ %d from %s\n",
-                      __func__, irq, node->devname);
-               return -ENXIO;
-       }
-
-       spin_lock_irqsave(&contr->lock, flags);
-
-       prev = irq_list + irq;
-       if (*prev) {
-               /* Can't share interrupts unless both agree to */
-               if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
-                       spin_unlock_irqrestore(&contr->lock, flags);
-                       return -EBUSY;
-               }
-               while (*prev)
-                       prev = &(*prev)->next;
-       }
-
-       if (!irq_list[irq]) {
-               if (contr->startup)
-                       contr->startup(irq);
-               else
-                       contr->enable(irq);
-       }
-       node->next = NULL;
-       *prev = node;
-
-       spin_unlock_irqrestore(&contr->lock, flags);
-
-       return 0;
-}
-
-int request_irq(unsigned int irq,
-               irq_handler_t handler,
-               unsigned long flags, const char *devname, void *dev_id)
-{
-       struct irq_node *node;
-       int res;
-
-       node = new_irq_node();
-       if (!node)
-               return -ENOMEM;
-
-       node->handler = handler;
-       node->flags   = flags;
-       node->dev_id  = dev_id;
-       node->devname = devname;
-
-       res = setup_irq(irq, node);
-       if (res)
-               node->handler = NULL;
-
-       return res;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-       struct irq_controller *contr;
-       struct irq_node **p, *node;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-               printk("%s: Incorrect IRQ %d\n", __func__, irq);
-               return;
-       }
-
-       spin_lock_irqsave(&contr->lock, flags);
-
-       p = irq_list + irq;
-       while ((node = *p)) {
-               if (node->dev_id == dev_id)
-                       break;
-               p = &node->next;
-       }
-
-       if (node) {
-               *p = node->next;
-               node->handler = NULL;
-       } else
-               printk("%s: Removing probably wrong IRQ %d\n",
-                      __func__, irq);
-
-       if (!irq_list[irq]) {
-               if (contr->shutdown)
-                       contr->shutdown(irq);
-               else
-                       contr->disable(irq);
-       }
-
-       spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(free_irq);
-
-void enable_irq(unsigned int irq)
-{
-       struct irq_controller *contr;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-               printk("%s: Incorrect IRQ %d\n",
-                      __func__, irq);
-               return;
-       }
-
-       spin_lock_irqsave(&contr->lock, flags);
-       if (irq_depth[irq]) {
-               if (!--irq_depth[irq]) {
-                       if (contr->enable)
-                               contr->enable(irq);
-               }
-       } else
-               WARN_ON(1);
-       spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(enable_irq);
-
-void disable_irq(unsigned int irq)
-{
-       struct irq_controller *contr;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-               printk("%s: Incorrect IRQ %d\n",
-                      __func__, irq);
-               return;
-       }
-
-       spin_lock_irqsave(&contr->lock, flags);
-       if (!irq_depth[irq]++) {
-               if (contr->disable)
-                       contr->disable(irq);
-       }
-       spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(disable_irq);
-
-void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
-
-EXPORT_SYMBOL(disable_irq_nosync);
-
-int m68k_irq_startup(unsigned int irq)
+unsigned int m68k_irq_startup_irq(unsigned int irq)
 {
        if (irq <= IRQ_AUTO_7)
                vectors[VEC_SPUR + irq] = auto_inthandler;
@@ -339,41 +141,21 @@ int m68k_irq_startup(unsigned int irq)
        return 0;
 }
 
-void m68k_irq_shutdown(unsigned int irq)
+unsigned int m68k_irq_startup(struct irq_data *data)
 {
-       if (irq <= IRQ_AUTO_7)
-               vectors[VEC_SPUR + irq] = bad_inthandler;
-       else
-               vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
+       return m68k_irq_startup_irq(data->irq);
 }
 
-
-/*
- * Do we need these probe functions on the m68k?
- *
- *  ... may be useful with ISA devices
- */
-unsigned long probe_irq_on (void)
+void m68k_irq_shutdown(struct irq_data *data)
 {
-#ifdef CONFIG_Q40
-       if (MACH_IS_Q40)
-               return q40_probe_irq_on();
-#endif
-       return 0;
-}
+       unsigned int irq = data->irq;
 
-EXPORT_SYMBOL(probe_irq_on);
-
-int probe_irq_off (unsigned long irqs)
-{
-#ifdef CONFIG_Q40
-       if (MACH_IS_Q40)
-               return q40_probe_irq_off(irqs);
-#endif
-       return 0;
+       if (irq <= IRQ_AUTO_7)
+               vectors[VEC_SPUR + irq] = bad_inthandler;
+       else
+               vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
 }
 
-EXPORT_SYMBOL(probe_irq_off);
 
 unsigned int irq_canonicalize(unsigned int irq)
 {
@@ -386,52 +168,9 @@ unsigned int irq_canonicalize(unsigned int irq)
 
 EXPORT_SYMBOL(irq_canonicalize);
 
-asmlinkage void m68k_handle_int(unsigned int irq)
-{
-       struct irq_node *node;
-       kstat_cpu(0).irqs[irq]++;
-       node = irq_list[irq];
-       do {
-               node->handler(irq, node->dev_id);
-               node = node->next;
-       } while (node);
-}
-
-asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs)
-{
-       struct pt_regs *old_regs;
-       old_regs = set_irq_regs(regs);
-       m68k_handle_int(irq);
-       set_irq_regs(old_regs);
-}
 
 asmlinkage void handle_badint(struct pt_regs *regs)
 {
-       kstat_cpu(0).irqs[0]++;
-       printk("unexpected interrupt from %u\n", regs->vector);
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-       struct irq_controller *contr;
-       struct irq_node *node;
-       int i = *(loff_t *) v;
-
-       /* autovector interrupts */
-       if (irq_list[i]) {
-               contr = irq_controller[i];
-               node = irq_list[i];
-               seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
-               while ((node = node->next))
-                       seq_printf(p, ", %s", node->devname);
-               seq_puts(p, "\n");
-       }
-       return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-void init_irq_proc(void)
-{
-       /* Insert /proc/irq driver here */
+       atomic_inc(&irq_err_count);
+       pr_warn("unexpected interrupt from %u\n", regs->vector);
 }
-#endif
index 2a96bebd8969eb6ef304a00c8f833e010465881c..b403924a1cad16f8ddeaf35da8003a3803041eca 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/traps.h>
 #include <asm/bootinfo.h>
@@ -20,9 +21,6 @@
 
 /* #define DEBUG_IRQS */
 
-extern void mac_enable_irq(unsigned int);
-extern void mac_disable_irq(unsigned int);
-
 int baboon_present;
 static volatile struct baboon *baboon;
 static unsigned char baboon_disabled;
@@ -53,7 +51,7 @@ void __init baboon_init(void)
  * Baboon interrupt handler. This works a lot like a VIA.
  */
 
-static irqreturn_t baboon_irq(int irq, void *dev_id)
+static void baboon_irq(unsigned int irq, struct irq_desc *desc)
 {
        int irq_bit, irq_num;
        unsigned char events;
@@ -64,15 +62,16 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
                (uint) baboon->mb_status);
 #endif
 
-       if (!(events = baboon->mb_ifr & 0x07))
-               return IRQ_NONE;
+       events = baboon->mb_ifr & 0x07;
+       if (!events)
+               return;
 
        irq_num = IRQ_BABOON_0;
        irq_bit = 1;
        do {
                if (events & irq_bit) {
                        baboon->mb_ifr &= ~irq_bit;
-                       m68k_handle_int(irq_num);
+                       generic_handle_irq(irq_num);
                }
                irq_bit <<= 1;
                irq_num++;
@@ -82,7 +81,6 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
        /* for now we need to smash all interrupts */
        baboon->mb_ifr &= ~events;
 #endif
-       return IRQ_HANDLED;
 }
 
 /*
@@ -92,8 +90,7 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
 void __init baboon_register_interrupts(void)
 {
        baboon_disabled = 0;
-       if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
-               pr_err("Couldn't register baboon interrupt\n");
+       irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq);
 }
 
 /*
@@ -111,7 +108,7 @@ void baboon_irq_enable(int irq)
 
        baboon_disabled &= ~(1 << irq_idx);
        if (!baboon_disabled)
-               mac_enable_irq(IRQ_NUBUS_C);
+               mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C));
 }
 
 void baboon_irq_disable(int irq)
@@ -124,7 +121,7 @@ void baboon_irq_disable(int irq)
 
        baboon_disabled |= 1 << irq_idx;
        if (baboon_disabled)
-               mac_disable_irq(IRQ_NUBUS_C);
+               mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C));
 }
 
 void baboon_irq_clear(int irq)
index 1ad4e9d80eba7f5be93f530c262636136a01b5b8..a5462cc0bfd65b70da36089b4ba6c45ef9b8c5cf 100644 (file)
@@ -305,15 +305,13 @@ void __init iop_register_interrupts(void)
 {
        if (iop_ism_present) {
                if (oss_present) {
-                       if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
-                                       IRQ_FLG_LOCK, "ISM IOP",
-                                       (void *) IOP_NUM_ISM))
+                       if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0,
+                                       "ISM IOP", (void *)IOP_NUM_ISM))
                                pr_err("Couldn't register ISM IOP interrupt\n");
                        oss_irq_enable(IRQ_MAC_ADB);
                } else {
-                       if (request_irq(IRQ_VIA2_0, iop_ism_irq,
-                                       IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
-                                       (void *) IOP_NUM_ISM))
+                       if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP",
+                                       (void *)IOP_NUM_ISM))
                                pr_err("Couldn't register ISM IOP interrupt\n");
                }
                if (!iop_alive(iop_base[IOP_NUM_ISM])) {
index f92190c159b47f48ee0648d64c0a353f87488477..ba220b70ab8cc5ea150c54707f366de876afa934 100644 (file)
@@ -190,14 +190,10 @@ irqreturn_t mac_debug_handler(int, void *);
 
 /* #define DEBUG_MACINTS */
 
-void mac_enable_irq(unsigned int irq);
-void mac_disable_irq(unsigned int irq);
-
-static struct irq_controller mac_irq_controller = {
+static struct irq_chip mac_irq_chip = {
        .name           = "mac",
-       .lock           = __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock),
-       .enable         = mac_enable_irq,
-       .disable        = mac_disable_irq,
+       .irq_enable     = mac_irq_enable,
+       .irq_disable    = mac_irq_disable,
 };
 
 void __init mac_init_IRQ(void)
@@ -205,7 +201,7 @@ void __init mac_init_IRQ(void)
 #ifdef DEBUG_MACINTS
        printk("mac_init_IRQ(): Setting things up...\n");
 #endif
-       m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
+       m68k_setup_irq_controller(&mac_irq_chip, handle_simple_irq, IRQ_USER,
                                  NUM_MAC_SOURCES - IRQ_USER);
        /* Make sure the SONIC interrupt is cleared or things get ugly */
 #ifdef SHUTUP_SONIC
@@ -241,16 +237,17 @@ void __init mac_init_IRQ(void)
 }
 
 /*
- *  mac_enable_irq - enable an interrupt source
- * mac_disable_irq - disable an interrupt source
+ *  mac_irq_enable - enable an interrupt source
+ * mac_irq_disable - disable an interrupt source
  *   mac_clear_irq - clears a pending interrupt
- * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending)
+ * mac_irq_pending - returns the pending status of an IRQ (nonzero = pending)
  *
  * These routines are just dispatchers to the VIA/OSS/PSC routines.
  */
 
-void mac_enable_irq(unsigned int irq)
+void mac_irq_enable(struct irq_data *data)
 {
+       int irq = data->irq;
        int irq_src = IRQ_SRC(irq);
 
        switch(irq_src) {
@@ -283,8 +280,9 @@ void mac_enable_irq(unsigned int irq)
        }
 }
 
-void mac_disable_irq(unsigned int irq)
+void mac_irq_disable(struct irq_data *data)
 {
+       int irq = data->irq;
        int irq_src = IRQ_SRC(irq);
 
        switch(irq_src) {
index a9c0f5ab4cc0251213dd8e1e034f7007d9d8a6d9..a4c82dab9ff1acd3d9d5f90aafa8fb2c55a913f9 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 int oss_present;
 volatile struct mac_oss *oss;
 
-static irqreturn_t oss_irq(int, void *);
-static irqreturn_t oss_nubus_irq(int, void *);
-
-extern irqreturn_t via1_irq(int, void *);
+extern void via1_irq(unsigned int irq, struct irq_desc *desc);
 
 /*
  * Initialize the OSS
@@ -59,26 +57,6 @@ void __init oss_init(void)
        oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1;
 }
 
-/*
- * Register the OSS and NuBus interrupt dispatchers.
- */
-
-void __init oss_register_interrupts(void)
-{
-       if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
-                       "scsi", (void *) oss))
-               pr_err("Couldn't register %s interrupt\n", "scsi");
-       if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
-                       "nubus", (void *) oss))
-               pr_err("Couldn't register %s interrupt\n", "nubus");
-       if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
-                       "sound", (void *) oss))
-               pr_err("Couldn't register %s interrupt\n", "sound");
-       if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
-                       "via1", (void *) via1))
-               pr_err("Couldn't register %s interrupt\n", "via1");
-}
-
 /*
  * Initialize OSS for Nubus access
  */
@@ -92,17 +70,17 @@ void __init oss_nubus_init(void)
  * and SCSI; everything else is routed to its own autovector IRQ.
  */
 
-static irqreturn_t oss_irq(int irq, void *dev_id)
+static void oss_irq(unsigned int irq, struct irq_desc *desc)
 {
        int events;
 
        events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
        if (!events)
-               return IRQ_NONE;
+               return;
 
 #ifdef DEBUG_IRQS
        if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
-               printk("oss_irq: irq %d events = 0x%04X\n", irq,
+               printk("oss_irq: irq %u events = 0x%04X\n", irq,
                        (int) oss->irq_pending);
        }
 #endif
@@ -113,11 +91,10 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
                /* FIXME: call sound handler */
        } else if (events & OSS_IP_SCSI) {
                oss->irq_pending &= ~OSS_IP_SCSI;
-               m68k_handle_int(IRQ_MAC_SCSI);
+               generic_handle_irq(IRQ_MAC_SCSI);
        } else {
                /* FIXME: error check here? */
        }
-       return IRQ_HANDLED;
 }
 
 /*
@@ -126,13 +103,13 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
  * Unlike the VIA/RBV this is on its own autovector interrupt level.
  */
 
-static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
+static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
 {
        int events, irq_bit, i;
 
        events = oss->irq_pending & OSS_IP_NUBUS;
        if (!events)
-               return IRQ_NONE;
+               return;
 
 #ifdef DEBUG_NUBUS_INT
        if (console_loglevel > 7) {
@@ -148,10 +125,21 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
                irq_bit >>= 1;
                if (events & irq_bit) {
                        oss->irq_pending &= ~irq_bit;
-                       m68k_handle_int(NUBUS_SOURCE_BASE + i);
+                       generic_handle_irq(NUBUS_SOURCE_BASE + i);
                }
        } while(events & (irq_bit - 1));
-       return IRQ_HANDLED;
+}
+
+/*
+ * Register the OSS and NuBus interrupt dispatchers.
+ */
+
+void __init oss_register_interrupts(void)
+{
+       irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
+       irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
+       irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq);
+       irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
 }
 
 /*
index a4c3eb60706ebc8266fe4eeb377c36b30f0b8ba9..e6c2d20f328d0599192994721fe72b3f1adaf90a 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/traps.h>
 #include <asm/bootinfo.h>
@@ -30,8 +31,6 @@
 int psc_present;
 volatile __u8 *psc;
 
-irqreturn_t psc_irq(int, void *);
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
@@ -111,53 +110,53 @@ void __init psc_init(void)
        }
 }
 
-/*
- * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
- */
-
-void __init psc_register_interrupts(void)
-{
-       if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
-               pr_err("Couldn't register psc%d interrupt\n", 3);
-       if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
-               pr_err("Couldn't register psc%d interrupt\n", 4);
-       if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
-               pr_err("Couldn't register psc%d interrupt\n", 5);
-       if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
-               pr_err("Couldn't register psc%d interrupt\n", 6);
-}
-
 /*
  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
  */
 
-irqreturn_t psc_irq(int irq, void *dev_id)
+static void psc_irq(unsigned int irq, struct irq_desc *desc)
 {
-       int pIFR        = pIFRbase + ((int) dev_id);
-       int pIER        = pIERbase + ((int) dev_id);
+       unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
+       int pIFR        = pIFRbase + offset;
+       int pIER        = pIERbase + offset;
        int irq_num;
        unsigned char irq_bit, events;
 
 #ifdef DEBUG_IRQS
-       printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
+       printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n",
                irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
 #endif
 
        events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
        if (!events)
-               return IRQ_NONE;
+               return;
 
        irq_num = irq << 3;
        irq_bit = 1;
        do {
                if (events & irq_bit) {
                        psc_write_byte(pIFR, irq_bit);
-                       m68k_handle_int(irq_num);
+                       generic_handle_irq(irq_num);
                }
                irq_num++;
                irq_bit <<= 1;
        } while (events >= irq_bit);
-       return IRQ_HANDLED;
+}
+
+/*
+ * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
+ */
+
+void __init psc_register_interrupts(void)
+{
+       irq_set_chained_handler(IRQ_AUTO_3, psc_irq);
+       irq_set_handler_data(IRQ_AUTO_3, (void *)0x30);
+       irq_set_chained_handler(IRQ_AUTO_4, psc_irq);
+       irq_set_handler_data(IRQ_AUTO_4, (void *)0x40);
+       irq_set_chained_handler(IRQ_AUTO_5, psc_irq);
+       irq_set_handler_data(IRQ_AUTO_5, (void *)0x50);
+       irq_set_chained_handler(IRQ_AUTO_6, psc_irq);
+       irq_set_handler_data(IRQ_AUTO_6, (void *)0x60);
 }
 
 void psc_irq_enable(int irq) {
index e71166daec6adf5507f3aef1ef8d53ab996bdf7c..f1600ad2662113979a16631613e6b8135c1a09e2 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
@@ -77,9 +78,6 @@ static int gIER,gIFR,gBufA,gBufB;
 static u8 nubus_disabled;
 
 void via_debug_dump(void);
-irqreturn_t via1_irq(int, void *);
-irqreturn_t via2_irq(int, void *);
-irqreturn_t via_nubus_irq(int, void *);
 void via_irq_enable(int irq);
 void via_irq_disable(int irq);
 void via_irq_clear(int irq);
@@ -281,39 +279,10 @@ void __init via_init_clock(irq_handler_t func)
        via1[vT1CL] = MAC_CLOCK_LOW;
        via1[vT1CH] = MAC_CLOCK_HIGH;
 
-       if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
+       if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
                pr_err("Couldn't register %s interrupt\n", "timer");
 }
 
-/*
- * Register the interrupt dispatchers for VIA or RBV machines only.
- */
-
-void __init via_register_interrupts(void)
-{
-       if (via_alt_mapping) {
-               if (request_irq(IRQ_AUTO_1, via1_irq,
-                               IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
-                               (void *) via1))
-                       pr_err("Couldn't register %s interrupt\n", "software");
-               if (request_irq(IRQ_AUTO_6, via1_irq,
-                               IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-                               (void *) via1))
-                       pr_err("Couldn't register %s interrupt\n", "via1");
-       } else {
-               if (request_irq(IRQ_AUTO_1, via1_irq,
-                               IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-                               (void *) via1))
-                       pr_err("Couldn't register %s interrupt\n", "via1");
-       }
-       if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-                       "via2", (void *) via2))
-               pr_err("Couldn't register %s interrupt\n", "via2");
-       if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
-                       IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
-               pr_err("Couldn't register %s interrupt\n", "nubus");
-}
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
@@ -446,48 +415,46 @@ void __init via_nubus_init(void)
  * via6522.c :-), disable/pending masks added.
  */
 
-irqreturn_t via1_irq(int irq, void *dev_id)
+void via1_irq(unsigned int irq, struct irq_desc *desc)
 {
        int irq_num;
        unsigned char irq_bit, events;
 
        events = via1[vIFR] & via1[vIER] & 0x7F;
        if (!events)
-               return IRQ_NONE;
+               return;
 
        irq_num = VIA1_SOURCE_BASE;
        irq_bit = 1;
        do {
                if (events & irq_bit) {
                        via1[vIFR] = irq_bit;
-                       m68k_handle_int(irq_num);
+                       generic_handle_irq(irq_num);
                }
                ++irq_num;
                irq_bit <<= 1;
        } while (events >= irq_bit);
-       return IRQ_HANDLED;
 }
 
-irqreturn_t via2_irq(int irq, void *dev_id)
+static void via2_irq(unsigned int irq, struct irq_desc *desc)
 {
        int irq_num;
        unsigned char irq_bit, events;
 
        events = via2[gIFR] & via2[gIER] & 0x7F;
        if (!events)
-               return IRQ_NONE;
+               return;
 
        irq_num = VIA2_SOURCE_BASE;
        irq_bit = 1;
        do {
                if (events & irq_bit) {
                        via2[gIFR] = irq_bit | rbv_clear;
-                       m68k_handle_int(irq_num);
+                       generic_handle_irq(irq_num);
                }
                ++irq_num;
                irq_bit <<= 1;
        } while (events >= irq_bit);
-       return IRQ_HANDLED;
 }
 
 /*
@@ -495,7 +462,7 @@ irqreturn_t via2_irq(int irq, void *dev_id)
  * VIA2 dispatcher as a fast interrupt handler.
  */
 
-irqreturn_t via_nubus_irq(int irq, void *dev_id)
+void via_nubus_irq(unsigned int irq, struct irq_desc *desc)
 {
        int slot_irq;
        unsigned char slot_bit, events;
@@ -506,7 +473,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
        else
                events &= ~via2[vDirA];
        if (!events)
-               return IRQ_NONE;
+               return;
 
        do {
                slot_irq = IRQ_NUBUS_F;
@@ -514,7 +481,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
                do {
                        if (events & slot_bit) {
                                events &= ~slot_bit;
-                               m68k_handle_int(slot_irq);
+                               generic_handle_irq(slot_irq);
                        }
                        --slot_irq;
                        slot_bit >>= 1;
@@ -528,7 +495,24 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
                else
                        events &= ~via2[vDirA];
        } while (events);
-       return IRQ_HANDLED;
+}
+
+/*
+ * Register the interrupt dispatchers for VIA or RBV machines only.
+ */
+
+void __init via_register_interrupts(void)
+{
+       if (via_alt_mapping) {
+               /* software interrupt */
+               irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
+               /* via1 interrupt */
+               irq_set_chained_handler(IRQ_AUTO_6, via1_irq);
+       } else {
+               irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
+       }
+       irq_set_chained_handler(IRQ_AUTO_2, via2_irq);
+       irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq);
 }
 
 void via_irq_enable(int irq) {
index 6cb9c3a9b6c955c013ee0185c23138ac3346f745..5de924ef42ed128b78631e5096e0f85ebdac31a9 100644 (file)
@@ -81,7 +81,7 @@ static void mvme147_get_model(char *model)
 
 void __init mvme147_init_IRQ(void)
 {
-       m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+       m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 void __init config_mvme147(void)
@@ -114,8 +114,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
        tick_handler = timer_routine;
-       if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
-                       "timer 1", NULL))
+       if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL))
                pr_err("Couldn't register timer interrupt\n");
 
        /* Init the clock with a value */
index 0b28e26216535c2212b4bd03610d503a1b82b275..31a66d99cbca3a7fb4bb66960f849c7f0c7d7f0a 100644 (file)
@@ -117,7 +117,7 @@ static void mvme16x_get_hardware_list(struct seq_file *m)
 
 static void __init mvme16x_init_IRQ (void)
 {
-       m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+       m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 #define pcc2chip       ((volatile u_char *)0xfff42000)
index 9f0e3d59bf923e240bbe648a1d2e304659f38a23..2b888491f29a121b9c2a605285937a453e188d69 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
-#include <asm/irq.h>
 #include <asm/traps.h>
 
 #include <asm/q40_master.h>
 */
 
 static void q40_irq_handler(unsigned int, struct pt_regs *fp);
-static void q40_enable_irq(unsigned int);
-static void q40_disable_irq(unsigned int);
+static void q40_irq_enable(struct irq_data *data);
+static void q40_irq_disable(struct irq_data *data);
 
 unsigned short q40_ablecount[35];
 unsigned short q40_state[35];
 
-static int q40_irq_startup(unsigned int irq)
+static unsigned int q40_irq_startup(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        /* test for ISA ints not implemented by HW */
        switch (irq) {
        case 1: case 2: case 8: case 9:
        case 11: case 12: case 13:
                printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq);
-               return -ENXIO;
+               /* FIXME return -ENXIO; */
        }
        return 0;
 }
 
-static void q40_irq_shutdown(unsigned int irq)
+static void q40_irq_shutdown(struct irq_data *data)
 {
 }
 
-static struct irq_controller q40_irq_controller = {
+static struct irq_chip q40_irq_chip = {
        .name           = "q40",
-       .lock           = __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock),
-       .startup        = q40_irq_startup,
-       .shutdown       = q40_irq_shutdown,
-       .enable         = q40_enable_irq,
-       .disable        = q40_disable_irq,
+       .irq_startup    = q40_irq_startup,
+       .irq_shutdown   = q40_irq_shutdown,
+       .irq_enable     = q40_irq_enable,
+       .irq_disable    = q40_irq_disable,
 };
 
 /*
@@ -81,13 +82,14 @@ static int disabled;
 
 void __init q40_init_IRQ(void)
 {
-       m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
+       m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1,
+                                 Q40_IRQ_MAX);
 
        /* setup handler for ISA ints */
        m68k_setup_auto_interrupt(q40_irq_handler);
 
-       m68k_irq_startup(IRQ_AUTO_2);
-       m68k_irq_startup(IRQ_AUTO_4);
+       m68k_irq_startup_irq(IRQ_AUTO_2);
+       m68k_irq_startup_irq(IRQ_AUTO_4);
 
        /* now enable some ints.. */
        master_outb(1, EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
@@ -218,11 +220,11 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
        switch (irq) {
        case 4:
        case 6:
-               __m68k_handle_int(Q40_IRQ_SAMPLE, fp);
+               do_IRQ(Q40_IRQ_SAMPLE, fp);
                return;
        }
        if (mir & Q40_IRQ_FRAME_MASK) {
-               __m68k_handle_int(Q40_IRQ_FRAME, fp);
+               do_IRQ(Q40_IRQ_FRAME, fp);
                master_outb(-1, FRAME_CLEAR_REG);
        }
        if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
@@ -257,7 +259,7 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
                                        goto iirq;
                                }
                                q40_state[irq] |= IRQ_INPROGRESS;
-                               __m68k_handle_int(irq, fp);
+                               do_IRQ(irq, fp);
                                q40_state[irq] &= ~IRQ_INPROGRESS;
 
                                /* naively enable everything, if that fails than    */
@@ -288,25 +290,29 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
        mir = master_inb(IIRQ_REG);
        /* should test whether keyboard irq is really enabled, doing it in defhand */
        if (mir & Q40_IRQ_KEYB_MASK)
-               __m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
+               do_IRQ(Q40_IRQ_KEYBOARD, fp);
 
        return;
 }
 
-void q40_enable_irq(unsigned int irq)
+void q40_irq_enable(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        if (irq >= 5 && irq <= 15) {
                mext_disabled--;
                if (mext_disabled > 0)
-                       printk("q40_enable_irq : nested disable/enable\n");
+                       printk("q40_irq_enable : nested disable/enable\n");
                if (mext_disabled == 0)
                        master_outb(1, EXT_ENABLE_REG);
        }
 }
 
 
-void q40_disable_irq(unsigned int irq)
+void q40_irq_disable(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        /* disable ISA iqs : only do something if the driver has been
         * verified to be Q40 "compatible" - right now IDE, NE2K
         * Any driver should not attempt to sleep across disable_irq !!
@@ -319,13 +325,3 @@ void q40_disable_irq(unsigned int irq)
                        printk("disable_irq nesting count %d\n",mext_disabled);
        }
 }
-
-unsigned long q40_probe_irq_on(void)
-{
-       printk("irq probing not working - reconfigure the driver to avoid this\n");
-       return -1;
-}
-int q40_probe_irq_off(unsigned long irqs)
-{
-       return -1;
-}
index 6464ad3ae3e6fe303732a8ab83a6eacf96473c20..78b60f53e90af7f668dd64ab3cf9071a66d59276 100644 (file)
@@ -51,25 +51,29 @@ void sun3_disable_irq(unsigned int irq)
 
 static irqreturn_t sun3_int7(int irq, void *dev_id)
 {
-       *sun3_intreg |=  (1 << irq);
-       if (!(kstat_cpu(0).irqs[irq] % 2000))
-               sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]);
+       unsigned int cnt;
+
+       cnt = kstat_irqs_cpu(irq, 0);
+       if (!(cnt % 2000))
+               sun3_leds(led_pattern[cnt % 16000 / 2000]);
        return IRQ_HANDLED;
 }
 
 static irqreturn_t sun3_int5(int irq, void *dev_id)
 {
+       unsigned int cnt;
+
 #ifdef CONFIG_SUN3
        intersil_clear();
 #endif
-        *sun3_intreg |=  (1 << irq);
 #ifdef CONFIG_SUN3
        intersil_clear();
 #endif
        xtime_update(1);
        update_process_times(user_mode(get_irq_regs()));
-        if (!(kstat_cpu(0).irqs[irq] % 20))
-                sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
+       cnt = kstat_irqs_cpu(irq, 0);
+       if (!(cnt % 20))
+               sun3_leds(led_pattern[cnt % 160 / 20]);
        return IRQ_HANDLED;
 }
 
@@ -79,29 +83,33 @@ static irqreturn_t sun3_vec255(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
+static void sun3_irq_enable(struct irq_data *data)
 {
-        *sun3_intreg &= ~(1 << irq);
+    sun3_enable_irq(data->irq);
+};
 
-       __m68k_handle_int(irq, fp);
-}
+static void sun3_irq_disable(struct irq_data *data)
+{
+    sun3_disable_irq(data->irq);
+};
 
-static struct irq_controller sun3_irq_controller = {
+static struct irq_chip sun3_irq_chip = {
        .name           = "sun3",
-       .lock           = __SPIN_LOCK_UNLOCKED(sun3_irq_controller.lock),
-       .startup        = m68k_irq_startup,
-       .shutdown       = m68k_irq_shutdown,
-       .enable         = sun3_enable_irq,
-       .disable        = sun3_disable_irq,
+       .irq_startup    = m68k_irq_startup,
+       .irq_shutdown   = m68k_irq_shutdown,
+       .irq_enable     = sun3_irq_enable,
+       .irq_disable    = sun3_irq_disable,
+       .irq_mask       = sun3_irq_disable,
+       .irq_unmask     = sun3_irq_enable,
 };
 
 void __init sun3_init_IRQ(void)
 {
        *sun3_intreg = 1;
 
-       m68k_setup_auto_interrupt(sun3_inthandle);
-       m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
-       m68k_setup_user_interrupt(VEC_USER, 128, NULL);
+       m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1,
+                                 7);
+       m68k_setup_user_interrupt(VEC_USER, 128);
 
        if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
                pr_err("Couldn't register %s interrupt\n", "int5");
diff --git a/arch/microblaze/include/asm/namei.h b/arch/microblaze/include/asm/namei.h
deleted file mode 100644 (file)
index 61d60b8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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_NAMEI_H
-#define _ASM_MICROBLAZE_NAMEI_H
-
-#ifdef __KERNEL__
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-#define __emul_prefix() NULL
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_MICROBLAZE_NAMEI_H */
index 9b4cb00407d7c468f607213f88dd729731a588be..0be318609fc62832c44fa6a47b1c9670c1e9b2b7 100644 (file)
@@ -286,11 +286,11 @@ CLEAN_FILES += vmlinux.32 vmlinux.64
 archprepare:
 ifdef CONFIG_MIPS32_N32
        @echo '  Checking missing-syscalls for N32'
-       $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32"
+       $(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=n32"
 endif
 ifdef CONFIG_MIPS32_O32
        @echo '  Checking missing-syscalls for O32'
-       $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32"
+       $(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=32"
 endif
 
 install:
index 975c20327bb152e4774f24f05a273bc4bbeb3a28..0a430e06f5e5e11f3989265a1f49336d1b10abee 100644 (file)
@@ -17,8 +17,6 @@
 
 static struct map_info flash_map;
 static struct mtd_info *mymtd;
-static int nr_parts;
-static struct mtd_partition *parts;
 static const char *part_probe_types[] = {
        "cmdlinepart",
 #ifdef CONFIG_MTD_REDBOOT_PARTS
@@ -61,11 +59,8 @@ static int __init flash_init(void)
                mymtd = do_map_probe("cfi_probe", &flash_map);
                if (mymtd) {
                        mymtd->owner = THIS_MODULE;
-
-                       nr_parts = parse_mtd_partitions(mymtd,
-                                                       part_probe_types,
-                                                       &parts, 0);
-                       mtd_device_register(mymtd, parts, nr_parts);
+                       mtd_device_parse_register(mymtd, part_probe_types,
+                                                 0, NULL, 0);
                } else {
                        pr_err("Failed to register MTD device for flash\n");
                }
index 8b606423bbd7f84dcacd4b043297844fc59200d4..efcfff4d4627c55f4238bfd3361fe937be25465e 100644 (file)
@@ -207,8 +207,9 @@ void octeon_prepare_cpus(unsigned int max_cpus)
         * the other bits alone.
         */
        cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffff);
-       if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
-                       "SMP-IPI", mailbox_interrupt)) {
+       if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt,
+                       IRQF_PERCPU | IRQF_NO_THREAD, "SMP-IPI",
+                       mailbox_interrupt)) {
                panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
        }
 }
index 708f08761406fe3bfdbd308822f163a2ae7c9822..cae42259d6da9cc49efd4ceb8bccdbad941fe3d0 100644 (file)
@@ -50,7 +50,7 @@ void __init prom_init(void)
 
        /* arg[0] is "g", the rest is boot parameters */
        for (i = 1; i < argc; i++) {
-               if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+               if (strlen(arcs_cmdline) + strlen(arg[i]) + 1
                    >= sizeof(arcs_cmdline))
                        break;
                strcat(arcs_cmdline, arg[i]);
index 76961cabeedfe1cdac4caaef7e9989ca04a345be..2ef17e8df40346f07aea6e01431186686214a1f7 100644 (file)
@@ -36,6 +36,8 @@ static inline int gpio_get_value(unsigned gpio)
        return -EINVAL;
 }
 
+#define gpio_get_value_cansleep        gpio_get_value
+
 static inline void gpio_set_value(unsigned gpio, int value)
 {
        switch (bcm47xx_bus_type) {
@@ -54,6 +56,19 @@ static inline void gpio_set_value(unsigned gpio, int value)
        }
 }
 
+#define gpio_set_value_cansleep gpio_set_value
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+       return 0;
+}
+
+static inline int gpio_is_valid(unsigned gpio)
+{
+       return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
+}
+
+
 static inline int gpio_direction_input(unsigned gpio)
 {
        switch (bcm47xx_bus_type) {
@@ -137,7 +152,4 @@ static inline int gpio_polarity(unsigned gpio, int value)
 }
 
 
-/* cansleep wrappers */
-#include <asm-generic/gpio.h>
-
 #endif /* __BCM47XX_GPIO_H */
index ecea7871dec28f6e4e44e1652a2d10b87e8a87b1..d8dad5340ea30d22eac825883012a14341fbf157 100644 (file)
 #define __NR_syncfs                    (__NR_Linux + 342)
 #define __NR_sendmmsg                  (__NR_Linux + 343)
 #define __NR_setns                     (__NR_Linux + 344)
+#define __NR_process_vm_readv          (__NR_Linux + 345)
+#define __NR_process_vm_writev         (__NR_Linux + 346)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            344
+#define __NR_Linux_syscalls            346
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                344
+#define __NR_O32_Linux_syscalls                346
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_syncfs                    (__NR_Linux + 301)
 #define __NR_sendmmsg                  (__NR_Linux + 302)
 #define __NR_setns                     (__NR_Linux + 303)
+#define __NR_process_vm_readv          (__NR_Linux + 304)
+#define __NR_process_vm_writev         (__NR_Linux + 305)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            303
+#define __NR_Linux_syscalls            305
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         303
+#define __NR_64_Linux_syscalls         305
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_syncfs                    (__NR_Linux + 306)
 #define __NR_sendmmsg                  (__NR_Linux + 307)
 #define __NR_setns                     (__NR_Linux + 308)
+#define __NR_process_vm_readv          (__NR_Linux + 309)
+#define __NR_process_vm_writev         (__NR_Linux + 310)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            308
+#define __NR_Linux_syscalls            310
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                308
+#define __NR_N32_Linux_syscalls                310
 
 #ifdef __KERNEL__
 
index 98c5a9737c14d2c200a161640122f9a8af053e88..e2d8e199be323345a6feaf3eb03a738e515dd5f5 100644 (file)
@@ -103,19 +103,10 @@ static int c0_compare_int_pending(void)
 
 /*
  * Compare interrupt can be routed and latched outside the core,
- * so a single execution hazard barrier may not be enough to give
- * it time to clear as seen in the Cause register.  4 time the
- * pipeline depth seems reasonably conservative, and empirically
- * works better in configurations with high CPU/bus clock ratios.
+ * so wait up to worst case number of cycle counter ticks for timer interrupt
+ * changes to propagate to the cause register.
  */
-
-#define compare_change_hazard() \
-       do { \
-               irq_disable_hazard(); \
-               irq_disable_hazard(); \
-               irq_disable_hazard(); \
-               irq_disable_hazard(); \
-       } while (0)
+#define COMPARE_INT_SEEN_TICKS 50
 
 int c0_compare_int_usable(void)
 {
@@ -126,8 +117,12 @@ int c0_compare_int_usable(void)
         * IP7 already pending?  Try to clear it by acking the timer.
         */
        if (c0_compare_int_pending()) {
-               write_c0_compare(read_c0_count());
-               compare_change_hazard();
+               cnt = read_c0_count();
+               write_c0_compare(cnt);
+               back_to_back_c0_hazard();
+               while (read_c0_count() < (cnt  + COMPARE_INT_SEEN_TICKS))
+                       if (!c0_compare_int_pending())
+                               break;
                if (c0_compare_int_pending())
                        return 0;
        }
@@ -136,7 +131,7 @@ int c0_compare_int_usable(void)
                cnt = read_c0_count();
                cnt += delta;
                write_c0_compare(cnt);
-               compare_change_hazard();
+               back_to_back_c0_hazard();
                if ((int)(read_c0_count() - cnt) < 0)
                    break;
                /* increase delta if the timer was already expired */
@@ -145,12 +140,17 @@ int c0_compare_int_usable(void)
        while ((int)(read_c0_count() - cnt) <= 0)
                ;       /* Wait for expiry  */
 
-       compare_change_hazard();
+       while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+               if (c0_compare_int_pending())
+                       break;
        if (!c0_compare_int_pending())
                return 0;
-
-       write_c0_compare(read_c0_count());
-       compare_change_hazard();
+       cnt = read_c0_count();
+       write_c0_compare(cnt);
+       back_to_back_c0_hazard();
+       while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+               if (!c0_compare_int_pending())
+                       break;
        if (c0_compare_int_pending())
                return 0;
 
index cefc6e259bafd3acd986588af2c87a6e3ce0f32d..5426779d9fdb77700d05b897e7af3acff8d753e1 100644 (file)
@@ -7,6 +7,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/platform_device.h>
 
index 47920657968d2e65368edd0c2cbd39c6a5052ef2..a632bc144efa1b9ca977a582864530e33ee039cb 100644 (file)
@@ -591,6 +591,8 @@ einval:     li      v0, -ENOSYS
        sys     sys_syncfs              1
        sys     sys_sendmmsg            4
        sys     sys_setns               2
+       sys     sys_process_vm_readv    6       /* 4345 */
+       sys     sys_process_vm_writev   6
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index fb7334bea7316aedd8071ff41d63178539504cc8..3b5a5e9ae49c132640c95a87037e48ac95e5b932 100644 (file)
@@ -430,4 +430,6 @@ sys_call_table:
        PTR     sys_syncfs
        PTR     sys_sendmmsg
        PTR     sys_setns
+       PTR     sys_process_vm_readv
+       PTR     sys_process_vm_writev           /* 5305 */
        .size   sys_call_table,.-sys_call_table
index 6de1f598346e3bfd527f1d3cad321160aedb3c02..6be6f7020923f1224260a0bf4df420a2d951db7a 100644 (file)
@@ -430,4 +430,6 @@ EXPORT(sysn32_call_table)
        PTR     sys_syncfs
        PTR     compat_sys_sendmmsg
        PTR     sys_setns
+       PTR     compat_sys_process_vm_readv
+       PTR     compat_sys_process_vm_writev    /* 6310 */
        .size   sysn32_call_table,.-sysn32_call_table
index 1d813169e453ea3709b0410521b8526638d96a98..54228553691d60903559706c00bc8a0d16a05b86 100644 (file)
@@ -548,4 +548,6 @@ sys_call_table:
        PTR     sys_syncfs
        PTR     compat_sys_sendmmsg
        PTR     sys_setns
+       PTR     compat_sys_process_vm_readv     /* 4345 */
+       PTR     compat_sys_process_vm_writev
        .size   sys_call_table,.-sys_call_table
index 261ccbc0774016aa6d055eb19dd82067f7ad65e8..5c8a49d55054dffce696066bad88d1863c5e7f35 100644 (file)
@@ -1596,7 +1596,8 @@ void __cpuinit per_cpu_trap_init(void)
        }
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-       cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+       if (!cpu_data[cpu].asid_cache)
+               cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
index 7e9c0ffc11a51c42bd58b1f465d54481aab6023c..77ed70fc2fe5953cd9bf31aa2514820b41e2bbd6 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
index 44a36771c819bebcb03732744566764c6d60b574..de1cb2bcd79a167e36b9602d14d6fa889e9a2b1d 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
index 56ba007bf1e59ee37d5a7a2627d603d635df447d..e34fcfd0d5ca5763983c2b0a248352275b40f49b 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
index 9b8af77ed0f9868baf4d1873121213cc6a8c556c..1ff6c9d6cb93eb6e21109f9a8c0a3f3941cba4a5 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <asm/bootinfo.h>
index 22d823acd536a3bcfee7708c90a593f57835d143..652258309c9c14220ebdbcaa5a43ac1faa01b7cc 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
index ddd39593c581453237b26e831716f853cd349a9d..696b1a3e06421d605097535384427ba7632e3396 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
index d0e32ab2ea074b9fa75ebd56e2c77ff1a15c994a..d614aa7ff07f48f89789694236aadf90b5f30004 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/mtd/physmap.h>
index 4278a459d6c483afd2f371fb856bff8eb1851714..cbb6ae5747b97f81c67c8d77916bd10bad34e125 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <lantiq_soc.h>
 #include <xway_dma.h>
index a321451a54554bc0cba17a0458e61436ce62801e..d2fa98f3c78d8185d6bfec384b88e23720829b88 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/ioport.h>
index a479355abdb92755759366fa1b50325474d93810..b91c7f17f10f043ae906c322e12669438e7f562a 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
index 67d59d69034063ab37dcffa6e4f135c7a531396b..ff9991cddeaa8c3fd6e44048730b09b6d24efb1f 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
index abe49f4db57f1ad670b6c6c6a6709bea6dcfe1e6..ae4959ae865c464cddd5da9393664f148fc448ca 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
index 1686692ac24d52eee2338feaebd3cdf943bb22e3..2228133ca3566a0e6a192a9191625f7f2078db28 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
index a1be36d0e490481b9fcdfdf6579e576ee115c111..3d41f0bb5bf73f0d84108129a979642770e632f7 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/pm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/reboot.h>
 
 #include <lantiq_soc.h>
diff --git a/arch/mips/nxp/pnx8550/common/pci.c b/arch/mips/nxp/pnx8550/common/pci.c
deleted file mode 100644 (file)
index 98e86dd..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *
- * Author: source@mvista.com
- *
- *  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/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <pci.h>
-#include <glb.h>
-#include <nand.h>
-
-static struct resource pci_io_resource = {
-       .start  = PNX8550_PCIIO + 0x1000,       /* reserve regacy I/O space */
-       .end    = PNX8550_PCIIO + PNX8550_PCIIO_SIZE,
-       .name   = "pci IO space",
-       .flags  = IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-       .start  = PNX8550_PCIMEM,
-       .end    = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1,
-       .name   = "pci memory space",
-       .flags  = IORESOURCE_MEM
-};
-
-extern struct pci_ops pnx8550_pci_ops;
-
-static struct pci_controller pnx8550_controller = {
-       .pci_ops        = &pnx8550_pci_ops,
-       .io_map_base    = PNX8550_PORT_BASE,
-       .io_resource    = &pci_io_resource,
-       .mem_resource   = &pci_mem_resource,
-};
-
-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
-static inline unsigned long get_system_mem_size(void)
-{
-       /* Read IP2031_RANK0_ADDR_LO */
-       unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
-       /* Read IP2031_RANK1_ADDR_HI */
-       unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
-
-       return dram_r1_hi - dram_r0_lo + 1;
-}
-
-static int __init pnx8550_pci_setup(void)
-{
-       int pci_mem_code;
-       int mem_size = get_system_mem_size() >> 20;
-
-       /* Clear the Global 2 Register, PCI Inta Output Enable Registers
-          Bit 1:Enable DAC Powerdown
-         -> 0:DACs are enabled and are working normally
-            1:DACs are powerdown
-          Bit 0:Enable of PCI inta output
-         -> 0 = Disable PCI inta output
-            1 = Enable PCI inta output
-       */
-       PNX8550_GLB2_ENAB_INTA_O = 0;
-
-       /* Calc the PCI mem size code */
-       if (mem_size >= 128)
-               pci_mem_code = SIZE_128M;
-       else if (mem_size >= 64)
-               pci_mem_code = SIZE_64M;
-       else if (mem_size >= 32)
-               pci_mem_code = SIZE_32M;
-       else
-               pci_mem_code = SIZE_16M;
-
-       /* Set PCI_XIO registers */
-       outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO);
-       outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI);
-       outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO);
-       outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI);
-
-       /* Send memory transaction via PCI_BASE2 */
-       outl(0x00000001, PCI_BASE | PCI_IO);
-
-       /* Unlock the setup register */
-       outl(0xca, PCI_BASE | PCI_UNLOCKREG);
-
-       /*
-        * BAR0 of PNX8550 (pci base 10) must be zero in order for ide
-        * to work, and in order for bus_to_baddr to work without any
-        * hacks.
-        */
-       outl(0x00000000, PCI_BASE | PCI_BASE10);
-
-       /*
-        *These two bars are set by default or the boot code.
-        * However, it's safer to set them here so we're not boot
-        * code dependent.
-        */
-       outl(0x1be00000, PCI_BASE | PCI_BASE14);  /* PNX MMIO */
-       outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18);  /* XIO      */
-
-       outl(PCI_EN_TA |
-            PCI_EN_PCI2MMI |
-            PCI_EN_XIO |
-            PCI_SETUP_BASE18_SIZE(SIZE_32M) |
-            PCI_SETUP_BASE18_EN |
-            PCI_SETUP_BASE14_EN |
-            PCI_SETUP_BASE10_PREF |
-            PCI_SETUP_BASE10_SIZE(pci_mem_code) |
-            PCI_SETUP_CFGMANAGE_EN |
-            PCI_SETUP_PCIARB_EN,
-            PCI_BASE |
-            PCI_SETUP);        /* PCI_SETUP */
-       outl(0x00000000, PCI_BASE | PCI_CTRL);  /* PCI_CONTROL */
-
-       register_pci_controller(&pnx8550_controller);
-
-       return 0;
-}
-
-arch_initcall(pnx8550_pci_setup);
diff --git a/arch/mips/nxp/pnx8550/common/setup.c b/arch/mips/nxp/pnx8550/common/setup.c
deleted file mode 100644 (file)
index 71adac3..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *
- * 2.6 port, Embedded Alley Solutions, Inc
- *
- *  Based on Per Hallsmark, per.hallsmark@mvista.com
- *
- *  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/sched.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/serial_pnx8xxx.h>
-#include <linux/pm.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/time.h>
-
-#include <glb.h>
-#include <int.h>
-#include <pci.h>
-#include <uart.h>
-#include <nand.h>
-
-extern void __init board_setup(void);
-extern void pnx8550_machine_restart(char *);
-extern void pnx8550_machine_halt(void);
-extern void pnx8550_machine_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-extern char *prom_getcmdline(void);
-
-struct resource standard_io_resources[] = {
-       {
-               .start  = 0x00,
-               .end    = 0x1f,
-               .name   = "dma1",
-               .flags  = IORESOURCE_BUSY
-       }, {
-               .start  = 0x40,
-               .end    = 0x5f,
-               .name   = "timer",
-               .flags  = IORESOURCE_BUSY
-       }, {
-               .start  = 0x80,
-               .end    = 0x8f,
-               .name   = "dma page reg",
-               .flags  = IORESOURCE_BUSY
-       }, {
-               .start  = 0xc0,
-               .end    = 0xdf,
-               .name   = "dma2",
-               .flags  = IORESOURCE_BUSY
-       },
-};
-
-#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources)
-
-extern struct resource pci_io_resource;
-extern struct resource pci_mem_resource;
-
-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
-unsigned long get_system_mem_size(void)
-{
-       /* Read IP2031_RANK0_ADDR_LO */
-       unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
-       /* Read IP2031_RANK1_ADDR_HI */
-       unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
-
-       return dram_r1_hi - dram_r0_lo + 1;
-}
-
-int pnx8550_console_port = -1;
-
-void __init plat_mem_setup(void)
-{
-       int i;
-       char* argptr;
-
-       board_setup();  /* board specific setup */
-
-        _machine_restart = pnx8550_machine_restart;
-        _machine_halt = pnx8550_machine_halt;
-        pm_power_off = pnx8550_machine_power_off;
-
-       /* Clear the Global 2 Register, PCI Inta Output Enable Registers
-          Bit 1:Enable DAC Powerdown
-         -> 0:DACs are enabled and are working normally
-            1:DACs are powerdown
-          Bit 0:Enable of PCI inta output
-         -> 0 = Disable PCI inta output
-            1 = Enable PCI inta output
-       */
-       PNX8550_GLB2_ENAB_INTA_O = 0;
-
-       /* IO/MEM resources. */
-       set_io_port_base(PNX8550_PORT_BASE);
-       ioport_resource.start = 0;
-       ioport_resource.end = ~0;
-       iomem_resource.start = 0;
-       iomem_resource.end = ~0;
-
-       /* Request I/O space for devices on this board */
-       for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-               request_resource(&ioport_resource, standard_io_resources + i);
-
-       /* Place the Mode Control bit for GPIO pin 16 in primary function */
-       /* Pin 16 is used by UART1, UA1_TX                                */
-       outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) |
-                       (PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT),
-                       PNX8550_GPIO_MC1);
-
-       argptr = prom_getcmdline();
-       if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
-               argptr += strlen("console=ttyS");
-               pnx8550_console_port = *argptr == '0' ? 0 : 1;
-
-               /* We must initialize the UART (console) before early printk */
-               /* Set LCR to 8-bit and BAUD to 38400 (no 5)                */
-               ip3106_lcr(UART_BASE, pnx8550_console_port) =
-                       PNX8XXX_UART_LCR_8BIT;
-               ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
-       }
-}
index 4ee57104e47bb78ef4b8957480e04de5ee8198b9..b5ce041cdafb54667b7c11738892ab7e9020000a 100644 (file)
@@ -7,6 +7,7 @@
  * Support for all devices (greater than 16) added by David Gathright.
  */
 
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
index 8656388b34bd4fac95d7dadf6584d9fe6cdbceb6..be1e1afe12c3ce3aa527b4142d8f8b7aee17143e 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 
 #include <asm/pci.h>
index cf4c868715acaaba37e9aec317d0224ca5b6d060..dcc926e06fcec573a4478b2359b2218d5ca942cf 100644 (file)
@@ -102,7 +102,7 @@ void __init prom_init(void)
 
        /* Get the boot parameters */
        for (i = 1; i < argc; i++) {
-               if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
+               if (strlen(arcs_cmdline) + strlen(arg[i]) + 1 >=
                    sizeof(arcs_cmdline))
                        break;
 
index b177caa56d95c5880f9a7d0732f1736dbb908598..951e18f5335b268965d3880881d900bed63e7356 100644 (file)
@@ -345,7 +345,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
 
 config KEXEC
        bool "kexec system call (EXPERIMENTAL)"
-       depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !47x)) && EXPERIMENTAL
+       depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 57af16edc19231ad0b4511f30174607a57711494..70ba0c0a1223d475cd2d2c2cdfddbf5b901a7527 100644 (file)
@@ -255,12 +255,6 @@ checkbin:
                echo 'disable kernel modules' ; \
                false ; \
        fi
-       @if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \
-               echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \
-               echo 'correctly with old versions of binutils.' ; \
-               echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \
-               false ; \
-       fi
 
 CLEAN_FILES += $(TOUT)
 
diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
new file mode 100644 (file)
index 0000000..0e00e50
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * charon board Device Tree Source
+ *
+ * Copyright (C) 2007 Semihalf
+ * Marian Balakowicz <m8@semihalf.com>
+ *
+ * Copyright (C) 2010 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.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.
+ */
+
+/dts-v1/;
+
+/ {
+       model = "anon,charon";
+       compatible = "anon,charon";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&mpc5200_pic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,5200@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <0x4000>;        // L1, 16K
+                       i-cache-size = <0x4000>;        // L1, 16K
+                       timebase-frequency = <0>;       // from bootloader
+                       bus-frequency = <0>;            // from bootloader
+                       clock-frequency = <0>;          // from bootloader
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x08000000>;  // 128MB
+       };
+
+       soc5200@f0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc5200-immr";
+               ranges = <0 0xf0000000 0x0000c000>;
+               reg = <0xf0000000 0x00000100>;
+               bus-frequency = <0>;            // from bootloader
+               system-frequency = <0>;         // from bootloader
+
+               cdm@200 {
+                       compatible = "fsl,mpc5200-cdm";
+                       reg = <0x200 0x38>;
+               };
+
+               mpc5200_pic: interrupt-controller@500 {
+                       // 5200 interrupts are encoded into two levels;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       compatible = "fsl,mpc5200-pic";
+                       reg = <0x500 0x80>;
+               };
+
+               timer@600 {     // General Purpose Timer
+                       compatible = "fsl,mpc5200-gpt";
+                       reg = <0x600 0x10>;
+                       interrupts = <1 9 0>;
+                       fsl,has-wdt;
+               };
+
+               can@900 {
+                       compatible = "fsl,mpc5200-mscan";
+                       interrupts = <2 17 0>;
+                       reg = <0x900 0x80>;
+               };
+
+               can@980 {
+                       compatible = "fsl,mpc5200-mscan";
+                       interrupts = <2 18 0>;
+                       reg = <0x980 0x80>;
+               };
+
+               gpio_simple: gpio@b00 {
+                       compatible = "fsl,mpc5200-gpio";
+                       reg = <0xb00 0x40>;
+                       interrupts = <1 7 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               usb@1000 {
+                       compatible = "fsl,mpc5200-ohci","ohci-be";
+                       reg = <0x1000 0xff>;
+                       interrupts = <2 6 0>;
+               };
+
+               dma-controller@1200 {
+                       device_type = "dma-controller";
+                       compatible = "fsl,mpc5200-bestcomm";
+                       reg = <0x1200 0x80>;
+                       interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+                                     3 4 0  3 5 0  3 6 0  3 7 0
+                                     3 8 0  3 9 0  3 10 0  3 11 0
+                                     3 12 0  3 13 0  3 14 0  3 15 0>;
+               };
+
+               xlb@1f00 {
+                       compatible = "fsl,mpc5200-xlb";
+                       reg = <0x1f00 0x100>;
+               };
+
+               serial@2000 {           // PSC1
+                       compatible = "fsl,mpc5200-psc-uart";
+                       reg = <0x2000 0x100>;
+                       interrupts = <2 1 0>;
+               };
+
+               serial@2400 {           // PSC3
+                       compatible = "fsl,mpc5200-psc-uart";
+                       reg = <0x2400 0x100>;
+                       interrupts = <2 3 0>;
+               };
+
+               ethernet@3000 {
+                       compatible = "fsl,mpc5200-fec";
+                       reg = <0x3000 0x400>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <2 5 0>;
+                       fixed-link = <1 1 100 0 0>;
+               };
+
+               mdio@3000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200-mdio";
+                       reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
+                       interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
+               };
+
+               ata@3a00 {
+                       compatible = "fsl,mpc5200-ata";
+                       reg = <0x3a00 0x100>;
+                       interrupts = <2 7 0>;
+               };
+
+               i2c@3d00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200-i2c","fsl-i2c";
+                       reg = <0x3d00 0x40>;
+                       interrupts = <2 15 0>;
+               };
+
+
+               i2c@3d40 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200-i2c","fsl-i2c";
+                       reg = <0x3d40 0x40>;
+                       interrupts = <2 16 0>;
+
+                       dtt@28 {
+                               compatible = "national,lm80";
+                               reg = <0x28>;
+                       };
+
+                       rtc@68 {
+                               compatible = "dallas,ds1374";
+                               reg = <0x68>;
+                       };
+               };
+
+               sram@8000 {
+                       compatible = "fsl,mpc5200-sram";
+                       reg = <0x8000 0x4000>;
+               };
+       };
+
+       localbus {
+               compatible = "fsl,mpc5200-lpb","simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <      0 0 0xfc000000 0x02000000
+                               1 0 0xe0000000 0x04000000 // CS1 range, SM501
+                               3 0 0xe8000000 0x00080000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x02000000>;
+                       bank-width = <4>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+               };
+
+               display@1,0 {
+                       compatible = "smi,sm501";
+                       reg = <1 0x00000000 0x00800000
+                              1 0x03e00000 0x00200000>;
+                       mode = "640x480-32@60";
+                       interrupts = <1 1 3>;
+                       little-endian;
+               };
+
+               mram0@3,0 {
+                       compatible = "mtd-ram";
+                       reg = <3 0x00000 0x80000>;
+                       bank-width = <1>;
+               };
+       };
+
+       pci@f0000d00 {
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               device_type = "pci";
+               compatible = "fsl,mpc5200-pci";
+               reg = <0xf0000d00 0x100>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+                                0xc000 0 0 2 &mpc5200_pic 0 0 3
+                                0xc000 0 0 3 &mpc5200_pic 0 0 3
+                                0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+               clock-frequency = <0>; // From boot loader
+               interrupts = <2 8 0 2 9 0 2 10 0>;
+               bus-range = <0 0>;
+               ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+                         0x02000000 0 0x90000000 0x90000000 0 0x10000000
+                         0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+       };
+};
index d9b776740a6739707d26a9ad836a39533bc8718c..d3b478242ea9586b793f9def431a6d9a4ea00c80 100644 (file)
                        interrupt-parent = <&mpic>;
                        interrupts = <16 2>;
                        interrupt-map-mask = <0xf800 0 0 7>;
+                       /* IRQ[0:3] are pulled up on board, set to active-low */
                        interrupt-map = <
                                /* IDSEL 0x0 */
                                0000 0 0 1 &mpic 0 1
                        interrupt-parent = <&mpic>;
                        interrupts = <16 2>;
                        interrupt-map-mask = <0xf800 0 0 7>;
+                       /*
+                        * IRQ[4:6] only for PCIe, set to active-high,
+                        * IRQ[7] is pulled up on board, set to active-low
+                        */
                        interrupt-map = <
                                /* IDSEL 0x0 */
-                               0000 0 0 1 &mpic 4 1
-                               0000 0 0 2 &mpic 5 1
-                               0000 0 0 3 &mpic 6 1
+                               0000 0 0 1 &mpic 4 2
+                               0000 0 0 2 &mpic 5 2
+                               0000 0 0 3 &mpic 6 2
                                0000 0 0 4 &mpic 7 1
                                >;
                        ranges = <0x2000000 0x0 0xa0000000
                        interrupt-parent = <&mpic>;
                        interrupts = <16 2>;
                        interrupt-map-mask = <0xf800 0 0 7>;
+                       /*
+                        * IRQ[8:10] are pulled up on board, set to active-low
+                        * IRQ[11] only for PCIe, set to active-high,
+                        */
                        interrupt-map = <
                                /* IDSEL 0x0 */
                                0000 0 0 1 &mpic 8 1
                                0000 0 0 2 &mpic 9 1
                                0000 0 0 3 &mpic 10 1
-                               0000 0 0 4 &mpic 11 1
+                               0000 0 0 4 &mpic 11 2
                                >;
                        ranges = <0x2000000 0x0 0x80000000
                                  0x2000000 0x0 0x80000000
index 959cd2cfc2756488fcbe4080a29b396653d5e8d5..716a37be16e33b5d071416592ca8eb39fc7cca2f 100644 (file)
@@ -1,9 +1,10 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
@@ -17,7 +18,6 @@ CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_BESTCOMM=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -38,17 +38,18 @@ CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_MISC_DEVICES is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
@@ -56,13 +57,11 @@ CONFIG_PATA_MPC52xx=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_LXT_PHY=y
+CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_FEC_MPC52xx=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
 CONFIG_SERIAL_MPC52xx=y
 CONFIG_SERIAL_MPC52xx_CONSOLE=y
 CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
@@ -70,7 +69,13 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SENSORS_LM80=y
 CONFIG_WATCHDOG=y
+CONFIG_MFD_SM501=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_SM501=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
@@ -80,10 +85,10 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
@@ -102,7 +107,6 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 6cdf1c0d2c8a10acc43796c20af80d52f7b78d64..3b98d735434142bb9240a6a2d4906d0b882a3ab2 100644 (file)
@@ -52,6 +52,8 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_JEDECPROBE=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_NAND=m
+CONFIG_MTD_NAND_NDFC=m
 CONFIG_MTD_UBI=m
 CONFIG_MTD_UBI_GLUEBI=m
 CONFIG_PROC_DEVICETREE=y
index 84a685a505fe115a39ebfbe99ce3baa399bf85d3..535711fcb13c54ad3f35adedfe7a0752f7991497 100644 (file)
@@ -485,3 +485,7 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_VHOST_NET=m
index 96a58b709705ccae5e071aa474f19b7f1a506ce0..a72f2415a64709193a20f6aa16b117da4f1ea075 100644 (file)
@@ -362,3 +362,7 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_VHOST_NET=m
index e2a4c26ad37793874dce3902d561dd749c78681d..02e41b53488d8d8574f42c6a4e0ce1f99df9aaa8 100644 (file)
@@ -49,13 +49,13 @@ static __inline__ int atomic_add_return(int a, atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%2         # atomic_add_return\n\
        add     %0,%1,%0\n"
        PPC405_ERR77(0,%2)
 "      stwcx.  %0,0,%2 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (a), "r" (&v->counter)
        : "cc", "memory");
@@ -85,13 +85,13 @@ static __inline__ int atomic_sub_return(int a, atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%2         # atomic_sub_return\n\
        subf    %0,%1,%0\n"
        PPC405_ERR77(0,%2)
 "      stwcx.  %0,0,%2 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (a), "r" (&v->counter)
        : "cc", "memory");
@@ -119,13 +119,13 @@ static __inline__ int atomic_inc_return(atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%1         # atomic_inc_return\n\
        addic   %0,%0,1\n"
        PPC405_ERR77(0,%1)
 "      stwcx.  %0,0,%1 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (&v->counter)
        : "cc", "xer", "memory");
@@ -163,13 +163,13 @@ static __inline__ int atomic_dec_return(atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%1         # atomic_dec_return\n\
        addic   %0,%0,-1\n"
        PPC405_ERR77(0,%1)
 "      stwcx.  %0,0,%1\n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (&v->counter)
        : "cc", "xer", "memory");
@@ -194,7 +194,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
        int t;
 
        __asm__ __volatile__ (
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%1         # __atomic_add_unless\n\
        cmpw    0,%0,%3 \n\
        beq-    2f \n\
@@ -202,7 +202,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
        PPC405_ERR77(0,%2)
 "      stwcx.  %0,0,%1 \n\
        bne-    1b \n"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
 "      subf    %0,%2,%0 \n\
 2:"
        : "=&r" (t)
@@ -226,7 +226,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%1         # atomic_dec_if_positive\n\
        cmpwi   %0,1\n\
        addi    %0,%0,-1\n\
@@ -234,7 +234,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
        PPC405_ERR77(0,%1)
 "      stwcx.  %0,0,%1\n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        "\n\
 2:"    : "=&b" (t)
        : "r" (&v->counter)
@@ -285,12 +285,12 @@ static __inline__ long atomic64_add_return(long a, atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%2         # atomic64_add_return\n\
        add     %0,%1,%0\n\
        stdcx.  %0,0,%2 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (a), "r" (&v->counter)
        : "cc", "memory");
@@ -319,12 +319,12 @@ static __inline__ long atomic64_sub_return(long a, atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%2         # atomic64_sub_return\n\
        subf    %0,%1,%0\n\
        stdcx.  %0,0,%2 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (a), "r" (&v->counter)
        : "cc", "memory");
@@ -351,12 +351,12 @@ static __inline__ long atomic64_inc_return(atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%1         # atomic64_inc_return\n\
        addic   %0,%0,1\n\
        stdcx.  %0,0,%1 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (&v->counter)
        : "cc", "xer", "memory");
@@ -393,12 +393,12 @@ static __inline__ long atomic64_dec_return(atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%1         # atomic64_dec_return\n\
        addic   %0,%0,-1\n\
        stdcx.  %0,0,%1\n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (&v->counter)
        : "cc", "xer", "memory");
@@ -418,13 +418,13 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%1         # atomic64_dec_if_positive\n\
        addic.  %0,%0,-1\n\
        blt-    2f\n\
        stdcx.  %0,0,%1\n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        "\n\
 2:"    : "=&r" (t)
        : "r" (&v->counter)
@@ -450,14 +450,14 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
        long t;
 
        __asm__ __volatile__ (
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%1         # __atomic_add_unless\n\
        cmpd    0,%0,%3 \n\
        beq-    2f \n\
        add     %0,%2,%0 \n"
 "      stdcx.  %0,0,%1 \n\
        bne-    1b \n"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
 "      subf    %0,%2,%0 \n\
 2:"
        : "=&r" (t)
index e137afcc10fae89cb0987bbe982af5653916e9e1..efdc92618b38ddfa7da075a53fb3ba93e9c71dae 100644 (file)
@@ -124,14 +124,14 @@ static __inline__ unsigned long fn(                       \
        return (old & mask);                            \
 }
 
-DEFINE_TESTOP(test_and_set_bits, or, PPC_RELEASE_BARRIER,
-             PPC_ACQUIRE_BARRIER, 0)
+DEFINE_TESTOP(test_and_set_bits, or, PPC_ATOMIC_ENTRY_BARRIER,
+             PPC_ATOMIC_EXIT_BARRIER, 0)
 DEFINE_TESTOP(test_and_set_bits_lock, or, "",
              PPC_ACQUIRE_BARRIER, 1)
-DEFINE_TESTOP(test_and_clear_bits, andc, PPC_RELEASE_BARRIER,
-             PPC_ACQUIRE_BARRIER, 0)
-DEFINE_TESTOP(test_and_change_bits, xor, PPC_RELEASE_BARRIER,
-             PPC_ACQUIRE_BARRIER, 0)
+DEFINE_TESTOP(test_and_clear_bits, andc, PPC_ATOMIC_ENTRY_BARRIER,
+             PPC_ATOMIC_EXIT_BARRIER, 0)
+DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER,
+             PPC_ATOMIC_EXIT_BARRIER, 0)
 
 static __inline__ int test_and_set_bit(unsigned long nr,
                                       volatile unsigned long *addr)
index 24bd34c57e9d020bac9f24dc3be933db06e6e019..936a904ae78c6c0712127de3b15d23ab5a5c0b18 100644 (file)
@@ -108,10 +108,10 @@ static int fd_request_irq(void)
 {
        if (can_use_virtual_dma)
                return request_irq(FLOPPY_IRQ, floppy_hardint,
-                                  IRQF_DISABLED, "floppy", NULL);
+                                  0, "floppy", NULL);
        else
                return request_irq(FLOPPY_IRQ, floppy_interrupt,
-                                  IRQF_DISABLED, "floppy", NULL);
+                                  0, "floppy", NULL);
 }
 
 static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
index c94e4a3fe2ef3de09decfd1aa47bda3b77342f53..2a9cf845473bb51a4aea7d5317dde0a4b5ab37ed 100644 (file)
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
   __asm__ __volatile ( \
-       PPC_RELEASE_BARRIER \
+       PPC_ATOMIC_ENTRY_BARRIER \
 "1:    lwarx   %0,0,%2\n" \
        insn \
        PPC405_ERR77(0, %2) \
 "2:    stwcx.  %1,0,%2\n" \
        "bne-   1b\n" \
+       PPC_ATOMIC_EXIT_BARRIER \
        "li     %1,0\n" \
 "3:    .section .fixup,\"ax\"\n" \
 "4:    li      %1,%3\n" \
@@ -92,14 +93,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                return -EFAULT;
 
         __asm__ __volatile__ (
-        PPC_RELEASE_BARRIER
+        PPC_ATOMIC_ENTRY_BARRIER
 "1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
         cmpw    0,%1,%4\n\
         bne-    3f\n"
         PPC405_ERR77(0,%3)
 "2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
-        PPC_ACQUIRE_BARRIER
+        PPC_ATOMIC_EXIT_BARRIER
 "3:    .section .fixup,\"ax\"\n\
 4:     li      %0,%6\n\
        b       3b\n\
index 08fe69edcd103f7882a3e172b7c5a55764009550..0ad432bc81d66259d82e4e94f691c46e4c765555 100644 (file)
@@ -148,12 +148,6 @@ struct kvm_regs {
 #define KVM_SREGS_E_UPDATE_DEC         (1 << 2)
 #define KVM_SREGS_E_UPDATE_DBSR                (1 << 3)
 
-/*
- * Book3S special bits to indicate contents in the struct by maintaining
- * backwards compatibility with older structs. If adding a new field,
- * please make sure to add a flag for that new field */
-#define KVM_SREGS_S_HIOR               (1 << 0)
-
 /*
  * In KVM_SET_SREGS, reserved/pad fields must be left untouched from a
  * previous KVM_GET_REGS.
@@ -179,8 +173,6 @@ struct kvm_sregs {
                                __u64 ibat[8]; 
                                __u64 dbat[8]; 
                        } ppc32;
-                       __u64 flags; /* KVM_SREGS_S_ */
-                       __u64 hior;
                } s;
                struct {
                        union {
index a384ffdf33de0af850ca03f18aab3e6c36515540..d4df013ad77964353fdf5a59c8ed6afde4ed1ce2 100644 (file)
@@ -90,8 +90,6 @@ struct kvmppc_vcpu_book3s {
 #endif
        int context_id[SID_CONTEXTS];
 
-       bool hior_sregs;                /* HIOR is set by SREGS, not PVR */
-
        struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE];
        struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG];
        struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE];
index 9cd5fc828a378e283639709d010902133a397feb..f77c708c67a05c2b576daec3476f74993a8d9ed6 100644 (file)
@@ -316,7 +316,7 @@ LV1_CALL(gpu_context_free,                              1, 0, 218 )
 LV1_CALL(gpu_context_iomap,                             5, 0, 221 )
 LV1_CALL(gpu_context_attribute,                         6, 0, 225 )
 LV1_CALL(gpu_context_intr,                              1, 1, 227 )
-LV1_CALL(gpu_attribute,                                 5, 0, 228 )
+LV1_CALL(gpu_attribute,                                 3, 0, 228 )
 LV1_CALL(get_rtc,                                       0, 2, 232 )
 LV1_CALL(set_ppe_periodic_tracer_frequency,             1, 0, 240 )
 LV1_CALL(start_ppe_periodic_tracer,                     5, 0, 241 )
index 28cdbd9f399c70fb5b9a9adf80863ca9758e390f..03c48e819c8e3ff3bc600242dc85ef9111aca478 100644 (file)
@@ -31,7 +31,7 @@
 
 #define MSR_           MSR_ME | MSR_CE
 #define MSR_KERNEL     MSR_ | MSR_64BIT
-#define MSR_USER32     MSR_ | MSR_PR | MSR_EE | MSR_DE
+#define MSR_USER32     MSR_ | MSR_PR | MSR_EE
 #define MSR_USER64     MSR_USER32 | MSR_64BIT
 #elif defined (CONFIG_40x)
 #define MSR_KERNEL     (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE)
index 6fbce725c710f97453079205e190c02c7365cd0b..a0f358d4a00cd57ba3b22fbbf1024c7daba65fa4 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifdef __powerpc64__
 
-extern char _end[];
+extern char __end_interrupts[];
 
 static inline int in_kernel_text(unsigned long addr)
 {
index d7cab44643c51d90f1f79509939e3c734b735eba..e682a7143edb767826705243df3613cc85e305ab 100644 (file)
@@ -13,6 +13,7 @@
 extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
 extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
                             void *fixup_end);
+extern void do_final_fixups(void);
 
 static inline void eieio(void)
 {
@@ -41,11 +42,15 @@ static inline void isync(void)
        START_LWSYNC_SECTION(97);                       \
        isync;                                          \
        MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
-#define PPC_ACQUIRE_BARRIER    "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
-#define PPC_RELEASE_BARRIER    stringify_in_c(LWSYNC) "\n"
+#define PPC_ACQUIRE_BARRIER     "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
+#define PPC_RELEASE_BARRIER     stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_EXIT_BARRIER         "\n" stringify_in_c(sync) "\n"
 #else
 #define PPC_ACQUIRE_BARRIER
 #define PPC_RELEASE_BARRIER
+#define PPC_ATOMIC_ENTRY_BARRIER
+#define PPC_ATOMIC_EXIT_BARRIER
 #endif
 
 #endif /* __KERNEL__ */
index bd6c401c0ee59a331fcf0eabdabe9b8205fde3df..c48de98ba94eef1c4ee98db7b79a33f270d47d04 100644 (file)
@@ -15,8 +15,8 @@
 #define        DEFAULT_PRIORITY        5
 
 /*
- * Mark IPIs as higher priority so we can take them inside interrupts that
- * arent marked IRQF_DISABLED
+ * Mark IPIs as higher priority so we can take them inside interrupts
+ * FIXME: still true now?
  */
 #define IPI_PRIORITY           4
 
index 56212bc0ab087c4b40bb21df3496c89849a01f06..4f80cf1ce77b84c30e905bcb8cb8d660c005c22b 100644 (file)
@@ -215,7 +215,22 @@ reenable_mmu:                              /* re-enable mmu so we can */
        stw     r9,8(r1)
        stw     r11,12(r1)
        stw     r3,ORIG_GPR3(r1)
+       /*
+        * The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1.
+        * If from user mode there is only one stack frame on the stack, and
+        * accessing CALLER_ADDR1 will cause oops. So we need create a dummy
+        * stack frame to make trace_hardirqs_off happy.
+        */
+       andi.   r12,r12,MSR_PR
+       beq     11f
+       stwu    r1,-16(r1)
+       bl      trace_hardirqs_off
+       addi    r1,r1,16
+       b       12f
+
+11:
        bl      trace_hardirqs_off
+12:
        lwz     r0,GPR0(r1)
        lwz     r3,ORIG_GPR3(r1)
        lwz     r4,GPR4(r1)
index a54d92fec6124377b0b03d13e26556a9055ff295..cf9c69b9189cb831261a8d8ca0c27d96aacfb89f 100644 (file)
@@ -267,7 +267,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
-       KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
 #endif /* CONFIG_CBE_RAS */
 
        STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
@@ -275,7 +275,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
-       KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
 #endif /* CONFIG_CBE_RAS */
 
        STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist)
@@ -283,7 +283,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal)
-       KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
 #endif /* CONFIG_CBE_RAS */
 
        . = 0x3000
index 368d158d665d5e44942f403d5a3710413ece52d2..a1ed8a8c7cb42c83fc61c674735f1f7d6bbe3842 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/jump_label.h>
 #include <asm/code-patching.h>
 
+#ifdef HAVE_JUMP_LABEL
 void arch_jump_label_transform(struct jump_entry *entry,
                               enum jump_label_type type)
 {
@@ -21,3 +22,4 @@ void arch_jump_label_transform(struct jump_entry *entry,
        else
                patch_instruction(addr, PPC_INST_NOP);
 }
+#endif
index 35f27646c4ff5af053313054c953000d0be64031..2985338d0e10164e3b77ab12fcc3bb755a1a6fb3 100644 (file)
@@ -132,7 +132,6 @@ static void kvm_patch_ins_b(u32 *inst, int addr)
        /* On relocatable kernels interrupts handlers and our code
           can be in different regions, so we don't patch them */
 
-       extern u32 __end_interrupts;
        if ((ulong)inst < (ulong)&__end_interrupts)
                return;
 #endif
index f7d760ab5ca1fd6851502352a7a958759c429c7f..7cd07b42ca1a505c9a9bfbb3802277336537a514 100644 (file)
@@ -738,7 +738,7 @@ relocate_new_kernel:
        mr      r5, r31
 
        li      r0, 0
-#elif defined(CONFIG_44x)  && !defined(CONFIG_47x)
+#elif defined(CONFIG_44x)  && !defined(CONFIG_PPC_47x)
 
 /*
  * Code for setting up 1:1 mapping for PPC440x for KEXEC
index 9054ca9ab4f93bcd6100cc0fcb03c7d5f4caf857..6457574c0b2f32fbaa800b11eeed0cbd8877a77e 100644 (file)
@@ -486,28 +486,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
        new_thread = &new->thread;
        old_thread = &current->thread;
 
-#if defined(CONFIG_PPC_BOOK3E_64)
-       /* XXX Current Book3E code doesn't deal with kernel side DBCR0,
-        * we always hold the user values, so we set it now.
-        *
-        * However, we ensure the kernel MSR:DE is appropriately cleared too
-        * to avoid spurrious single step exceptions in the kernel.
-        *
-        * This will have to change to merge with the ppc32 code at some point,
-        * but I don't like much what ppc32 is doing today so there's some
-        * thinking needed there
-        */
-       if ((new_thread->dbcr0 | old_thread->dbcr0) & DBCR0_IDM) {
-               u32 dbcr0;
-
-               mtmsr(mfmsr() & ~MSR_DE);
-               isync();
-               dbcr0 = mfspr(SPRN_DBCR0);
-               dbcr0 = (dbcr0 & DBCR0_EDM) | new_thread->dbcr0;
-               mtspr(SPRN_DBCR0, dbcr0);
-       }
-#endif /* CONFIG_PPC64_BOOK3E */
-
 #ifdef CONFIG_PPC64
        /*
         * Collect processor utilization data per process
@@ -657,7 +635,7 @@ void show_regs(struct pt_regs * regs)
        if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
                printk("CFAR: "REG"\n", regs->orig_gpr3);
        if (trap == 0x300 || trap == 0x600)
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
                printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
 #else
                printk("DAR: "REG", DSISR: %08lx\n", regs->dar, regs->dsisr);
index b4fa66127495286aa6d4e7030480492f2b6bf90b..cc584865b3df537d7c50cfb2bda9d87a6ed24f85 100644 (file)
@@ -1579,10 +1579,8 @@ static void __init prom_instantiate_rtas(void)
                return;
 
        base = alloc_down(size, PAGE_SIZE, 0);
-       if (base == 0) {
-               prom_printf("RTAS allocation failed !\n");
-               return;
-       }
+       if (base == 0)
+               prom_panic("Could not allocate memory for RTAS\n");
 
        rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
        if (!IHANDLE_VALID(rtas_inst)) {
index c1ce86357ecb4a3a47411c18e6fe88cfd5c07d8b..ac761081511355ee68854ee02ade12f17ef93e18 100644 (file)
@@ -107,6 +107,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
                         PTRRELOC(&__start___lwsync_fixup),
                         PTRRELOC(&__stop___lwsync_fixup));
 
+       do_final_fixups();
+
        return KERNELBASE + offset;
 }
 
index 1a9dea80a69b46a42b9df6ed4ce4d45f385abb85..fb9bb46e7e881a584c1532a6768622395a5045be 100644 (file)
@@ -359,6 +359,7 @@ void __init setup_system(void)
                          &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
        do_lwsync_fixups(cur_cpu_spec->cpu_features,
                         &__start___lwsync_fixup, &__stop___lwsync_fixup);
+       do_final_fixups();
 
        /*
         * Unflatten the device-tree passed by prom_init or kexec
index 78b76dc54dfb27847a24228e1bac2e2ef804354a..836a5a19eb2c3a3e45d5cab542fdb7138a8142bd 100644 (file)
@@ -97,7 +97,7 @@ static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
        compat_sigset_t cset;
 
        switch (_NSIG_WORDS) {
-       case 4: cset.sig[5] = set->sig[3] & 0xffffffffull;
+       case 4: cset.sig[6] = set->sig[3] & 0xffffffffull;
                cset.sig[7] = set->sig[3] >> 32;
        case 3: cset.sig[4] = set->sig[2] & 0xffffffffull;
                cset.sig[5] = set->sig[2] >> 32;
index 25ddbfc7dd367e21d8a6b7526d04d597f176545d..6df70907d60aba5cf244c5dade8ea007bc30425d 100644 (file)
@@ -187,7 +187,7 @@ int smp_request_message_ipi(int virq, int msg)
                return 1;
        }
 #endif
-       err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
+       err = request_irq(virq, smp_ipi_action[msg], IRQF_PERCPU,
                          smp_ipi_name[msg], 0);
        WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
                virq, smp_ipi_name[msg], err);
index 4e5908264d1a98819a6713fe23f4d5a23032db41..5459d148a0f6d792fd457bd55e2105788057169b 100644 (file)
@@ -1298,14 +1298,12 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
 
                if (user_mode(regs)) {
                        current->thread.dbcr0 &= ~DBCR0_IC;
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
                        if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0,
                                               current->thread.dbcr1))
                                regs->msr |= MSR_DE;
                        else
                                /* Make sure the IDM bit is off */
                                current->thread.dbcr0 &= ~DBCR0_IDM;
-#endif
                }
 
                _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
index 0cdbc07cec14e1cd9900a5b1eddc62e476dcdf98..0cb137a9b0381f1175d5962c67aac18f566af662 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/processor.h>
 #include <asm/cputhreads.h>
 #include <asm/page.h>
+#include <asm/hvcall.h>
 #include <linux/gfp.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
index f422231d92353771bcf663eb6dbb9393bcb161aa..44d8829334ab2d9c1ec22606336177d36f41b3d5 100644 (file)
@@ -1263,7 +1263,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
        addi    r6,r5,VCORE_NAPPING_THREADS
 31:    lwarx   r4,0,r6
        or      r4,r4,r0
-       popcntw r7,r4
+       PPC_POPCNTW(r7,r4)
        cmpw    r7,r8
        bge     2f
        stwcx.  r4,0,r6
index bc4d50dec78b8f420f789d722c38c66d42a87ab6..3c791e1eb675299c96e7b428b499e7bec4e5f434 100644 (file)
@@ -151,16 +151,14 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
 #ifdef CONFIG_PPC_BOOK3S_64
        if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
                kvmppc_mmu_book3s_64_init(vcpu);
-               if (!to_book3s(vcpu)->hior_sregs)
-                       to_book3s(vcpu)->hior = 0xfff00000;
+               to_book3s(vcpu)->hior = 0xfff00000;
                to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
                vcpu->arch.cpu_type = KVM_CPU_3S_64;
        } else
 #endif
        {
                kvmppc_mmu_book3s_32_init(vcpu);
-               if (!to_book3s(vcpu)->hior_sregs)
-                       to_book3s(vcpu)->hior = 0;
+               to_book3s(vcpu)->hior = 0;
                to_book3s(vcpu)->msr_mask = 0xffffffffULL;
                vcpu->arch.cpu_type = KVM_CPU_3S_32;
        }
@@ -797,9 +795,6 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
                }
        }
 
-       if (sregs->u.s.flags & KVM_SREGS_S_HIOR)
-               sregs->u.s.hior = to_book3s(vcpu)->hior;
-
        return 0;
 }
 
@@ -836,11 +831,6 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        /* Flush the MMU after messing with the segments */
        kvmppc_mmu_pte_flush(vcpu, 0, 0);
 
-       if (sregs->u.s.flags & KVM_SREGS_S_HIOR) {
-               to_book3s(vcpu)->hior_sregs = true;
-               to_book3s(vcpu)->hior = sregs->u.s.hior;
-       }
-
        return 0;
 }
 
index efbf9ad872035dee6a364867c5e5e50cdd52da99..607fbdf24b8484c173cc03593ffc71d968b689fe 100644 (file)
@@ -208,7 +208,6 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_PPC_BOOKE_SREGS:
 #else
        case KVM_CAP_PPC_SEGSTATE:
-       case KVM_CAP_PPC_HIOR:
        case KVM_CAP_PPC_PAPR:
 #endif
        case KVM_CAP_PPC_UNSET_IRQ:
index 0d08d0171392a4e7ec72e21226737cc458e3a98f..7a8a7487cee8dde9d06aa86fff3bd32bdd54433e 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/init.h>
 #include <asm/cputable.h>
 #include <asm/code-patching.h>
+#include <asm/page.h>
+#include <asm/sections.h>
 
 
 struct fixup_entry {
@@ -128,6 +130,27 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
        }
 }
 
+void do_final_fixups(void)
+{
+#if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
+       int *src, *dest;
+       unsigned long length;
+
+       if (PHYSICAL_START == 0)
+               return;
+
+       src = (int *)(KERNELBASE + PHYSICAL_START);
+       dest = (int *)KERNELBASE;
+       length = (__end_interrupts - _stext) / sizeof(int);
+
+       while (length--) {
+               patch_instruction(dest, *src);
+               src++;
+               dest++;
+       }
+#endif
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST
 
 #define check(x)       \
index 5964371303ac4a5941eb2a0ccceca27cf6330354..8558b572e55d3e6ba2ee7b5656b9eb9f9e39b5c3 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_fdt.h>
 #include <linux/memblock.h>
 #include <linux/bootmem.h>
+#include <linux/moduleparam.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
index 16da595ff4022aa56e7e053adde6e251439444e6..2dd6bdd31fe14f77a0bc097f746ca59e790f0b0e 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/suspend.h>
 #include <linux/memblock.h>
 #include <linux/hugetlb.h>
+#include <linux/slab.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -555,3 +556,32 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
                book3e_hugetlb_preload(vma->vm_mm, address, *ptep);
 #endif
 }
+
+/*
+ * System memory should not be in /proc/iomem but various tools expect it
+ * (eg kdump).
+ */
+static int add_system_ram_resources(void)
+{
+       struct memblock_region *reg;
+
+       for_each_memblock(memory, reg) {
+               struct resource *res;
+               unsigned long base = reg->base;
+               unsigned long size = reg->size;
+
+               res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+               WARN_ON(!res);
+
+               if (res) {
+                       res->name = "System RAM";
+                       res->start = base;
+                       res->end = base + size - 1;
+                       res->flags = IORESOURCE_MEM;
+                       WARN_ON(request_resource(&iomem_resource, res) < 0);
+               }
+       }
+
+       return 0;
+}
+subsys_initcall(add_system_ram_resources);
index c7dd4dec4df8c9d2826541fa2ae5c7e94dcb4051..b22a83a91cb852b92d023529e3f1b3bf011dce38 100644 (file)
@@ -315,7 +315,10 @@ static int __init find_min_common_depth(void)
        struct device_node *root;
        const char *vec5;
 
-       root = of_find_node_by_path("/rtas");
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               root = of_find_node_by_path("/ibm,opal");
+       else
+               root = of_find_node_by_path("/rtas");
        if (!root)
                root = of_find_node_by_path("/");
 
@@ -344,12 +347,19 @@ static int __init find_min_common_depth(void)
 
 #define VEC5_AFFINITY_BYTE     5
 #define VEC5_AFFINITY          0x80
-       chosen = of_find_node_by_path("/chosen");
-       if (chosen) {
-               vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL);
-               if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) {
-                       dbg("Using form 1 affinity\n");
-                       form1_affinity = 1;
+
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               form1_affinity = 1;
+       else {
+               chosen = of_find_node_by_path("/chosen");
+               if (chosen) {
+                       vec5 = of_get_property(chosen,
+                                              "ibm,architecture-vec-5", NULL);
+                       if (vec5 && (vec5[VEC5_AFFINITY_BYTE] &
+                                                       VEC5_AFFINITY)) {
+                               dbg("Using form 1 affinity\n");
+                               form1_affinity = 1;
+                       }
                }
        }
 
index e36d6e232ae66f4bf3033e5b60363cea25e46008..846b789fb1953000d15f90f1da723f0b0d81ff43 100644 (file)
@@ -50,6 +50,7 @@ static void __init mpc5200_simple_setup_arch(void)
 
 /* list of the supported boards */
 static const char *board[] __initdata = {
+       "anon,charon",
        "intercontrol,digsy-mtc",
        "manroland,mucmc52",
        "manroland,uc101",
index 45023e26aea369685d88c752aa52814ac07dd27a..d7946be298b6fc1f842eaff3e14b4ae502924f3c 100644 (file)
@@ -203,7 +203,7 @@ config P3060_QDS
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
index 01dcf44871e9a4c79273d14efd1fcde0b60b6ba9..081cf4ac188161b4f4bb535d0d57209bc14fd03c 100644 (file)
@@ -70,7 +70,7 @@ define_machine(p3060_qds) {
        .power_save             = e500_idle,
 };
 
-machine_device_initcall(p3060_qds, declare_of_platform_devices);
+machine_device_initcall(p3060_qds, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier);
index e4588721ef344da86b4cc001179e2e778bbde4cd..3fe6d927ad70e928d302192d275fd0b69220af05 100644 (file)
@@ -347,7 +347,7 @@ config SIMPLE_GPIO
 
 config MCU_MPC8349EMITX
        bool "MPC8349E-mITX MCU driver"
-       depends on I2C && PPC_83xx
+       depends on I2C=y && PPC_83xx
        select GENERIC_GPIO
        select ARCH_REQUIRE_GPIOLIB
        help
index 232fc384e8553386c5b7405d349151f4e6e5eaf0..852592b2b7128e0fd72b41dca54f123e827240df 100644 (file)
@@ -230,7 +230,7 @@ static int __init beat_register_event(void)
                }
                ev->virq = virq;
 
-               rc = request_irq(virq, ev->handler, IRQF_DISABLED,
+               rc = request_irq(virq, ev->handler, 0,
                                      ev->typecode, NULL);
                if (rc != 0) {
                        printk(KERN_ERR "Beat: failed to request virtual IRQ"
index ae790ac4a589182b3f1e4a5873396cbcd71fdc6f..14be2bd358b83e1c3ac71d964e8ba92c08c0536e 100644 (file)
@@ -514,7 +514,7 @@ static __init int celleb_setup_pciex(struct device_node *node,
        virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
                                     oirq.size);
        if (request_irq(virq, pciex_handle_internal_irq,
-                       IRQF_DISABLED, "pciex", (void *)phb)) {
+                       0, "pciex", (void *)phb)) {
                pr_err("PCIEXC:Failed to request irq\n");
                goto error;
        }
index fc46fcac392199e6ad5fd8c1862b28ae2cb8e1b3..592c3d51b8178e5af2b2c8b552ebbfde177e4323 100644 (file)
@@ -412,8 +412,7 @@ static void cell_iommu_enable_hardware(struct cbe_iommu *iommu)
                        IIC_IRQ_IOEX_ATI | (iommu->nid << IIC_IRQ_NODE_SHIFT));
        BUG_ON(virq == NO_IRQ);
 
-       ret = request_irq(virq, ioc_interrupt, IRQF_DISABLED,
-                       iommu->name, iommu);
+       ret = request_irq(virq, ioc_interrupt, 0, iommu->name, iommu);
        BUG_ON(ret);
 
        /* set the IOC segment table origin register (and turn on the iommu) */
index 1acf360104234862cb8c2bb40516cc99c22c05eb..59c1a1694104f0a4048e23b75535fe4eaa4f0068 100644 (file)
@@ -392,7 +392,7 @@ static int __init cbe_init_pm_irq(void)
                }
 
                rc = request_irq(irq, cbe_pm_irq,
-                                IRQF_DISABLED, "cbe-pmu-0", NULL);
+                                0, "cbe-pmu-0", NULL);
                if (rc) {
                        printk("ERROR: Request for irq on node %d failed\n",
                               node);
index 3675da73623f156fb86528b8d9132b7399d72a17..e94d3ecdd8bbc7ceff338c2016272103d5bbf2d4 100644 (file)
@@ -442,8 +442,7 @@ static int spu_request_irqs(struct spu *spu)
                snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0",
                         spu->number);
                ret = request_irq(spu->irqs[0], spu_irq_class_0,
-                                 IRQF_DISABLED,
-                                 spu->irq_c0, spu);
+                                 0, spu->irq_c0, spu);
                if (ret)
                        goto bail0;
        }
@@ -451,8 +450,7 @@ static int spu_request_irqs(struct spu *spu)
                snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1",
                         spu->number);
                ret = request_irq(spu->irqs[1], spu_irq_class_1,
-                                 IRQF_DISABLED,
-                                 spu->irq_c1, spu);
+                                 0, spu->irq_c1, spu);
                if (ret)
                        goto bail1;
        }
@@ -460,8 +458,7 @@ static int spu_request_irqs(struct spu *spu)
                snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2",
                         spu->number);
                ret = request_irq(spu->irqs[2], spu_irq_class_2,
-                                 IRQF_DISABLED,
-                                 spu->irq_c2, spu);
+                                 0, spu->irq_c2, spu);
                if (ret)
                        goto bail2;
        }
index cb40e921a56550f506385e065ca6b956a5471888..901bfbddc3ddcecea0e1d0dc35082ebb9d98d6ef 100644 (file)
@@ -272,7 +272,6 @@ static struct irqaction xmon_action = {
 
 static struct irqaction gatwick_cascade_action = {
        .handler        = gatwick_action,
-       .flags          = IRQF_DISABLED,
        .name           = "cascade",
 };
 
index 9a521dc8e485101637e4de9f948d427ec286e362..9b6a820bdd7dccb7f618f325206eec324b058d95 100644 (file)
@@ -200,7 +200,7 @@ static int psurge_secondary_ipi_init(void)
 
        if (psurge_secondary_virq)
                rc = request_irq(psurge_secondary_virq, psurge_ipi_intr,
-                       IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+                       IRQF_PERCPU, "IPI", NULL);
 
        if (rc)
                pr_err("Failed to setup secondary cpu IPI\n");
@@ -408,7 +408,7 @@ static int __init smp_psurge_kick_cpu(int nr)
 
 static struct irqaction psurge_irqaction = {
        .handler = psurge_ipi_intr,
-       .flags = IRQF_DISABLED|IRQF_PERCPU,
+       .flags = IRQF_PERCPU,
        .name = "primary IPI",
 };
 
index 6c4b5837fc8ab27965e66a1ca55689f92bbce975..3f175e8aedb499c4a94427d3c9a6028895c533df 100644 (file)
@@ -825,7 +825,7 @@ static int ps3_probe_thread(void *data)
 
        spin_lock_init(&dev.lock);
 
-       res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED,
+       res = request_irq(irq, ps3_notification_interrupt, 0,
                          "ps3_notification", &dev);
        if (res) {
                pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,
index 404bc52b7806e1f769455439626bb62ac0afbcf9..1d6f4f478fe293ebd06313aa1077c1019507473d 100644 (file)
@@ -88,6 +88,7 @@ struct ps3_private {
        struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
        u64 ppe_id;
        u64 thread_id;
+       unsigned long ipi_mask;
 };
 
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
@@ -144,7 +145,11 @@ static void ps3_chip_unmask(struct irq_data *d)
 static void ps3_chip_eoi(struct irq_data *d)
 {
        const struct ps3_private *pd = irq_data_get_irq_chip_data(d);
-       lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
+
+       /* non-IPIs are EOIed here. */
+
+       if (!test_bit(63 - d->irq, &pd->ipi_mask))
+               lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
 }
 
 /**
@@ -691,6 +696,16 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
                cpu, virq, pd->bmp.ipi_debug_brk_mask);
 }
 
+void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq)
+{
+       struct ps3_private *pd = &per_cpu(ps3_private, cpu);
+
+       set_bit(63 - virq, &pd->ipi_mask);
+
+       DBG("%s:%d: cpu %u, virq %u, ipi_mask %lxh\n", __func__, __LINE__,
+               cpu, virq, pd->ipi_mask);
+}
+
 static unsigned int ps3_get_irq(void)
 {
        struct ps3_private *pd = &__get_cpu_var(ps3_private);
@@ -720,6 +735,12 @@ static unsigned int ps3_get_irq(void)
                BUG();
        }
 #endif
+
+       /* IPIs are EOIed here. */
+
+       if (test_bit(63 - plug, &pd->ipi_mask))
+               lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, plug);
+
        return plug;
 }
 
index 9a196a88eda794d6d07f50abefaebc7a21902427..1a633ed0fe98744d8994d7e6367180a11ab59a96 100644 (file)
@@ -43,6 +43,7 @@ void ps3_mm_shutdown(void);
 void ps3_init_IRQ(void);
 void ps3_shutdown_IRQ(int cpu);
 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
+void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq);
 
 /* smp */
 
index 5e304c292f68e1e22e3fff9dd3527ae8a5f1bcd1..ca40f6afd35d5a0ed6043008740761558769e6fb 100644 (file)
@@ -184,7 +184,7 @@ int ps3_repository_read_bus_type(unsigned int bus_index,
        enum ps3_bus_type *bus_type)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -199,7 +199,7 @@ int ps3_repository_read_bus_num_dev(unsigned int bus_index,
        unsigned int *num_dev)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -239,7 +239,7 @@ int ps3_repository_read_dev_type(unsigned int bus_index,
        unsigned int dev_index, enum ps3_dev_type *dev_type)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -256,8 +256,8 @@ int ps3_repository_read_dev_intr(unsigned int bus_index,
        enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
 {
        int result;
-       u64 v1;
-       u64 v2;
+       u64 v1 = 0;
+       u64 v2 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -275,7 +275,7 @@ int ps3_repository_read_dev_reg_type(unsigned int bus_index,
        enum ps3_reg_type *reg_type)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -615,7 +615,7 @@ int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
        unsigned int dev_index, unsigned int *num_regions)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -631,7 +631,7 @@ int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
        unsigned int *region_id)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
            make_first_field("bus", bus_index),
@@ -786,7 +786,7 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -805,7 +805,7 @@ int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -827,8 +827,8 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index,
        enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
 {
        int result;
-       u64 v1;
-       u64 v2;
+       u64 v1 = 0;
+       u64 v2 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -854,7 +854,7 @@ static int ps3_repository_read_boot_dat_address(u64 *address)
 int ps3_repository_read_boot_dat_size(unsigned int *size)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -869,7 +869,7 @@ int ps3_repository_read_boot_dat_size(unsigned int *size)
 int ps3_repository_read_vuart_av_port(unsigned int *port)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -884,7 +884,7 @@ int ps3_repository_read_vuart_av_port(unsigned int *port)
 int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -919,7 +919,7 @@ int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
 int ps3_repository_read_num_be(unsigned int *num_be)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("ben", 0),
index 4c44794faac0b344ac50663ed12122519c37b53d..efc1cd8c034ac7f47135f7af1e1582d9e722984b 100644 (file)
@@ -59,46 +59,49 @@ static void ps3_smp_message_pass(int cpu, int msg)
 
 static int ps3_smp_probe(void)
 {
-       return 2;
-}
+       int cpu;
 
-static void __init ps3_smp_setup_cpu(int cpu)
-{
-       int result;
-       unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
-       int i;
+       for (cpu = 0; cpu < 2; cpu++) {
+               int result;
+               unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
+               int i;
 
-       DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
+               DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
-       /*
-        * Check assumptions on ps3_ipi_virqs[] indexing. If this
-        * check fails, then a different mapping of PPC_MSG_
-        * to index needs to be setup.
-        */
+               /*
+               * Check assumptions on ps3_ipi_virqs[] indexing. If this
+               * check fails, then a different mapping of PPC_MSG_
+               * to index needs to be setup.
+               */
 
-       BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
-       BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
-       BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
-       BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
+               BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
+               BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
+               BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
+               BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
 
-       for (i = 0; i < MSG_COUNT; i++) {
-               result = ps3_event_receive_port_setup(cpu, &virqs[i]);
+               for (i = 0; i < MSG_COUNT; i++) {
+                       result = ps3_event_receive_port_setup(cpu, &virqs[i]);
 
-               if (result)
-                       continue;
+                       if (result)
+                               continue;
 
-               DBG("%s:%d: (%d, %d) => virq %u\n",
-                       __func__, __LINE__, cpu, i, virqs[i]);
+                       DBG("%s:%d: (%d, %d) => virq %u\n",
+                               __func__, __LINE__, cpu, i, virqs[i]);
 
-               result = smp_request_message_ipi(virqs[i], i);
+                       result = smp_request_message_ipi(virqs[i], i);
 
-               if (result)
-                       virqs[i] = NO_IRQ;
-       }
+                       if (result)
+                               virqs[i] = NO_IRQ;
+                       else
+                               ps3_register_ipi_irq(cpu, virqs[i]);
+               }
 
-       ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
+               ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
 
-       DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
+               DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
+       }
+
+       return 2;
 }
 
 void ps3_smp_cleanup_cpu(int cpu)
@@ -121,7 +124,6 @@ static struct smp_ops_t ps3_smp_ops = {
        .probe          = ps3_smp_probe,
        .message_pass   = ps3_smp_message_pass,
        .kick_cpu       = smp_generic_kick_cpu,
-       .setup_cpu      = ps3_smp_setup_cpu,
 };
 
 void smp_init_ps3(void)
index af1a5df46b3e54ff75bb392b97ff26e8f1e72b4f..b6731e4a6646e16e81c62de273d8a6cd579b1ca7 100644 (file)
@@ -280,6 +280,7 @@ void __init ehv_pic_init(void)
 
        if (!ehv_pic->irqhost) {
                of_node_put(np);
+               kfree(ehv_pic);
                return;
        }
 
index c4d96fa32ba557a68512b133400fef585e799eb4..d5c3c90ee6981a14d40da0175f3d3ddc0c0f77f4 100644 (file)
@@ -328,6 +328,7 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
 err:
        iounmap(fsl_lbc_ctrl_dev->regs);
        kfree(fsl_lbc_ctrl_dev);
+       fsl_lbc_ctrl_dev = NULL;
        return ret;
 }
 
index de170fd5ba4eb8e2a4ff9d0d116f271aa7690a19..22ffccd8bef53b69a41fcfcfdf8fb3ed46b3d760 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/export.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
index 0842c6f8a3e67ae4059b4b5483840f517cdbb41f..8c7e8528e7c44cfe8f84db927f5ed454a7f99715 100644 (file)
@@ -800,8 +800,6 @@ static void mpic_end_ipi(struct irq_data *d)
         * IPIs are marked IRQ_PER_CPU. This has the side effect of
         * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
         * applying to them. We EOI them late to avoid re-entering.
-        * We mark IPI's with IRQF_DISABLED as they must run with
-        * irqs disabled.
         */
        mpic_eoi(mpic);
 }
index d3d6ce3c33b4740507dbfd0fdacdbd85e984047d..0debcc31ad7005084cb952025ff6fe6d9960f528 100644 (file)
@@ -115,7 +115,7 @@ static int __init ppc4xx_l2c_probe(void)
        }
 
        /* Install error handler */
-       if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) {
+       if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) {
                printk(KERN_ERR "Cannot install L2C error handler"
                       ", cache is not enabled\n");
                of_node_put(np);
index 3363fbc964f86c1d42676116f813a2ac71b9e0e2..ceb09cbd2329e782fe00a5c3e1326d217ab3e92b 100644 (file)
@@ -216,7 +216,7 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
        /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
           that the BRG divisor must be even if you're not using divide-by-16
           mode. */
-       if (!div16 && (divisor & 1))
+       if (!div16 && (divisor & 1) && (divisor > 3))
                divisor++;
 
        tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
index 3d93a8ded0f8f68fdf415f91d4072cdb29bb9454..63762c672a0372b7f2eb5469c85c63cd5617402a 100644 (file)
@@ -134,11 +134,10 @@ static void xics_request_ipi(void)
        BUG_ON(ipi == NO_IRQ);
 
        /*
-        * IPIs are marked IRQF_DISABLED as they must run with irqs
-        * disabled, and PERCPU.  The handler was set in map.
+        * IPIs are marked IRQF_PERCPU. The handler was set in map.
         */
        BUG_ON(request_irq(ipi, icp_ops->ipi_action,
-                          IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL));
+                          IRQF_PERCPU, "IPI", NULL));
 }
 
 int __init xics_smp_probe(void)
index a9fbd43395f71814d85a284a63900dc5a7dcc018..373679b3744a7992c7009281c1747b3aeb38157a 100644 (file)
@@ -572,6 +572,7 @@ config KEXEC
 config CRASH_DUMP
        bool "kernel crash dumps"
        depends on 64BIT
+       select KEXEC
        help
          Generate crash dump after being started by kexec.
          Crash dump kernels are loaded in the main kernel with kexec-tools
index 49676771bd66a278e73db7a2430612a57a1cf6a1..ffd1ac255f19444d838e58b2fb2ef2b716b02f77 100644 (file)
@@ -368,9 +368,12 @@ static inline int crypt_s390_func_available(int func,
 
        if (facility_mask & CRYPT_S390_MSA && !test_facility(17))
                return 0;
-       if (facility_mask & CRYPT_S390_MSA3 && !test_facility(76))
+
+       if (facility_mask & CRYPT_S390_MSA3 &&
+           (!test_facility(2) || !test_facility(76)))
                return 0;
-       if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
+       if (facility_mask & CRYPT_S390_MSA4 &&
+           (!test_facility(2) || !test_facility(77)))
                return 0;
 
        switch (func & CRYPT_S390_OP_MASK) {
index 24e18473d926548ec3e54732093902178a6838e9..b0c235cb6ad5c79d42414a863508e0c37db8337d 100644 (file)
@@ -47,7 +47,7 @@ struct sca_block {
 #define KVM_HPAGE_MASK(x)      (~(KVM_HPAGE_SIZE(x) - 1))
 #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
 
-#define CPUSTAT_HOST       0x80000000
+#define CPUSTAT_STOPPED    0x80000000
 #define CPUSTAT_WAIT       0x10000000
 #define CPUSTAT_ECALL_PEND 0x08000000
 #define CPUSTAT_STOP_INT   0x04000000
@@ -139,6 +139,7 @@ struct kvm_vcpu_stat {
        u32 instruction_stfl;
        u32 instruction_tprot;
        u32 instruction_sigp_sense;
+       u32 instruction_sigp_sense_running;
        u32 instruction_sigp_external_call;
        u32 instruction_sigp_emergency;
        u32 instruction_sigp_stop;
index 34ede0ea85a9d0ae6d03a8c52b3bb3f43cb4e1ac..524d23b8610ceb65c42661a97e79226125dbadf3 100644 (file)
@@ -593,6 +593,8 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)
        unsigned long address, bits;
        unsigned char skey;
 
+       if (!pte_present(*ptep))
+               return pgste;
        address = pte_val(*ptep) & PAGE_MASK;
        skey = page_get_storage_key(address);
        bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
@@ -625,6 +627,8 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
 #ifdef CONFIG_PGSTE
        int young;
 
+       if (!pte_present(*ptep))
+               return pgste;
        young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
        /* Transfer page referenced bit to pte software bit (host view) */
        if (young || (pgste_val(pgste) & RCP_HR_BIT))
@@ -638,13 +642,15 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
 
 }
 
-static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
+static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
 {
 #ifdef CONFIG_PGSTE
        unsigned long address;
        unsigned long okey, nkey;
 
-       address = pte_val(*ptep) & PAGE_MASK;
+       if (!pte_present(entry))
+               return;
+       address = pte_val(entry) & PAGE_MASK;
        okey = nkey = page_get_storage_key(address);
        nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
        /* Set page access key and fetch protection bit from pgste */
@@ -712,7 +718,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 
        if (mm_has_pgste(mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste_set_pte(ptep, pgste);
+               pgste_set_pte(ptep, pgste, entry);
                *ptep = entry;
                pgste_set_unlock(ptep, pgste);
        } else
index 5a099714df0459b9470e3d158e0b163bf8ce770b..097183c70407a81e9147697a37c880a6008b4ed1 100644 (file)
@@ -82,6 +82,7 @@ extern unsigned int user_mode;
 #define MACHINE_FLAG_LPAR      (1UL << 12)
 #define MACHINE_FLAG_SPP       (1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY  (1UL << 14)
+#define MACHINE_FLAG_STCKF     (1UL << 15)
 
 #define MACHINE_IS_VM          (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM         (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -100,6 +101,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF       (0)
 #define MACHINE_HAS_SPP                (0)
 #define MACHINE_HAS_TOPOLOGY   (0)
+#define MACHINE_HAS_STCKF      (0)
 #else /* __s390x__ */
 #define MACHINE_HAS_IEEE       (1)
 #define MACHINE_HAS_CSP                (1)
@@ -111,6 +113,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF       (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_SPP                (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_TOPOLOGY   (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
+#define MACHINE_HAS_STCKF      (S390_lowcore.machine_flags & MACHINE_FLAG_STCKF)
 #endif /* __s390x__ */
 
 #define ZFCPDUMP_HSA_SIZE      (32UL<<20)
index d610bef9c5e91a425ad01a683525f46ba0c055e1..c447a27a7fdb109be95edf0d6884026df6e895ce 100644 (file)
@@ -90,7 +90,7 @@ static inline unsigned long long get_clock_fast(void)
 {
        unsigned long long clk;
 
-       if (test_facility(25))
+       if (MACHINE_HAS_STCKF)
                asm volatile(".insn     s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
        else
                clk = get_clock();
index 404bdb9671b4f5c8d03d2391e93abf26e5b38a59..58de4c91c333358000779b283efdad2de1ebe445 100644 (file)
 #define __NR_clock_adjtime     337
 #define __NR_syncfs            338
 #define __NR_setns             339
-#define NR_syscalls 340
+#define __NR_process_vm_readv  340
+#define __NR_process_vm_writev 341
+#define NR_syscalls 342
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 5006a1d9f5d0ed6d3abd95f3cca652d87689dcef..18c51df9fe06c5ed98f785fb6af86655c025e887 100644 (file)
@@ -1627,3 +1627,23 @@ ENTRY(sys_setns_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_setns
+
+ENTRY(compat_sys_process_vm_readv_wrapper)
+       lgfr    %r2,%r2                 # compat_pid_t
+       llgtr   %r3,%r3                 # struct compat_iovec __user *
+       llgfr   %r4,%r4                 # unsigned long
+       llgtr   %r5,%r5                 # struct compat_iovec __user *
+       llgfr   %r6,%r6                 # unsigned long
+       llgf    %r0,164(%r15)           # unsigned long
+       stg     %r0,160(%r15)
+       jg      sys_process_vm_readv
+
+ENTRY(compat_sys_process_vm_writev_wrapper)
+       lgfr    %r2,%r2                 # compat_pid_t
+       llgtr   %r3,%r3                 # struct compat_iovec __user *
+       llgfr   %r4,%r4                 # unsigned long
+       llgtr   %r5,%r5                 # struct compat_iovec __user *
+       llgfr   %r6,%r6                 # unsigned long
+       llgf    %r0,164(%r15)           # unsigned long
+       stg     %r0,160(%r15)
+       jg      sys_process_vm_writev
index 37394b3413e2776dfd24586f0578045e488bd054..c9ffe002519715d64ddc16d2a2caafcbf47cb8b2 100644 (file)
@@ -390,6 +390,8 @@ static __init void detect_machine_facilities(void)
                S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
        if (test_facility(40))
                S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
+       if (test_facility(25))
+               S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF;
 #endif
 }
 
index 8ac6bfa2786cbe139d9964b1f4ab374e4302e2e8..e58a462949b164ea90c5697696b9ccec47bb7ff4 100644 (file)
@@ -211,6 +211,8 @@ static void __init setup_zfcpdump(unsigned int console_devno)
 
        if (ipl_info.type != IPL_TYPE_FCP_DUMP)
                return;
+       if (OLDMEM_BASE)
+               return;
        if (console_devno != -1)
                sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
                        ipl_info.data.fcp.dev_id.devno, console_devno);
@@ -482,7 +484,7 @@ static void __init setup_memory_end(void)
 
 
 #ifdef CONFIG_ZFCPDUMP
-       if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
+       if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) {
                memory_end = ZFCPDUMP_HSA_SIZE;
                memory_end_set = 1;
        }
index 73eb08c874fb450ef6ba0464d4aa4ca845bb6911..bcab2f04ba581f7648426a1790485d53626d8fda 100644 (file)
@@ -348,3 +348,5 @@ SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at
 SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper)
 SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
 SYSCALL(sys_setns,sys_setns,sys_setns_wrapper)
+SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */
+SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
index 77b8942b9a153af398cf9cf0e2dfd8eb7c5629ef..fdb5b8cb260f683e1f4559f95c006a7838690f60 100644 (file)
@@ -68,8 +68,10 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
        return mask;
 }
 
-static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
-                            struct mask_info *book, struct mask_info *core)
+static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
+                                         struct mask_info *book,
+                                         struct mask_info *core,
+                                         int z10)
 {
        unsigned int cpu;
 
@@ -88,10 +90,16 @@ static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
                        cpu_book_id[lcpu] = book->id;
 #endif
                        cpumask_set_cpu(lcpu, &core->mask);
-                       cpu_core_id[lcpu] = core->id;
+                       if (z10) {
+                               cpu_core_id[lcpu] = rcpu;
+                               core = core->next;
+                       } else {
+                               cpu_core_id[lcpu] = core->id;
+                       }
                        smp_cpu_polarization[lcpu] = tl_cpu->pp;
                }
        }
+       return core;
 }
 
 static void clear_masks(void)
@@ -123,18 +131,41 @@ static void tl_to_cores(struct sysinfo_15_1_x *info)
 {
 #ifdef CONFIG_SCHED_BOOK
        struct mask_info *book = &book_info;
+       struct cpuid cpu_id;
 #else
        struct mask_info *book = NULL;
 #endif
        struct mask_info *core = &core_info;
        union topology_entry *tle, *end;
+       int z10 = 0;
 
-
+#ifdef CONFIG_SCHED_BOOK
+       get_cpu_id(&cpu_id);
+       z10 = cpu_id.machine == 0x2097 || cpu_id.machine == 0x2098;
+#endif
        spin_lock_irq(&topology_lock);
        clear_masks();
        tle = info->tle;
        end = (union topology_entry *)((unsigned long)info + info->length);
        while (tle < end) {
+#ifdef CONFIG_SCHED_BOOK
+               if (z10) {
+                       switch (tle->nl) {
+                       case 1:
+                               book = book->next;
+                               book->id = tle->container.id;
+                               break;
+                       case 0:
+                               core = add_cpus_to_mask(&tle->cpu, book, core, z10);
+                               break;
+                       default:
+                               clear_masks();
+                               goto out;
+                       }
+                       tle = next_tle(tle);
+                       continue;
+               }
+#endif
                switch (tle->nl) {
 #ifdef CONFIG_SCHED_BOOK
                case 2:
@@ -147,7 +178,7 @@ static void tl_to_cores(struct sysinfo_15_1_x *info)
                        core->id = tle->container.id;
                        break;
                case 0:
-                       add_cpus_to_mask(&tle->cpu, book, core);
+                       add_cpus_to_mask(&tle->cpu, book, core, z10);
                        break;
                default:
                        clear_masks();
@@ -328,8 +359,8 @@ void __init s390_init_cpu_topology(void)
        for (i = 0; i < TOPOLOGY_NR_MAG; i++)
                printk(" %d", info->mag[i]);
        printk(" / %d\n", info->mnest);
-       alloc_masks(info, &core_info, 2);
+       alloc_masks(info, &core_info, 1);
 #ifdef CONFIG_SCHED_BOOK
-       alloc_masks(info, &book_info, 3);
+       alloc_masks(info, &book_info, 2);
 #endif
 }
index 56fe6bc81fee45804a61c37fb189ccf73a0b72e8..e4c79ebb40e628850fd230fc94a0c7fdc77aaeb1 100644 (file)
@@ -43,6 +43,8 @@ SECTIONS
 
        NOTES :text :note
 
+       .dummy : { *(.dummy) } :data
+
        RODATA
 
 #ifdef CONFIG_SHARED_KERNEL
index 87cedd61be0467fdd4085308e55967acb9210ef3..8943e82cd4d94248ef8708839d6c7e0d99e324f9 100644 (file)
@@ -70,7 +70,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
                return -EOPNOTSUPP;
        }
 
-       atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+       atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
        vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
        vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
        vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
index c7c51898984ef78e64b761ad8c6f9256fa71f30b..02434543eabbede6e5e2fbc17f8e649f5a19871a 100644 (file)
@@ -132,7 +132,6 @@ static int handle_stop(struct kvm_vcpu *vcpu)
        int rc = 0;
 
        vcpu->stat.exit_stop_request++;
-       atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        spin_lock_bh(&vcpu->arch.local_int.lock);
        if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
                vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
@@ -149,6 +148,8 @@ static int handle_stop(struct kvm_vcpu *vcpu)
        }
 
        if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
+               atomic_set_mask(CPUSTAT_STOPPED,
+                               &vcpu->arch.sie_block->cpuflags);
                vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
                VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
                rc = -EOPNOTSUPP;
index 87c16705b381396f796e7fbacbb079d62cab8d9d..278ee009ce6570a9d4049a095def51b17fb164d5 100644 (file)
@@ -252,6 +252,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
                        offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
                if (rc == -EFAULT)
                        exception = 1;
+               atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
                break;
 
        case KVM_S390_PROGRAM_INT:
index 0bd3bea1e4cdfc40069a474d37f74459903803ce..d1c445732451b6d1bd1c4b95db3d6467ff629c68 100644 (file)
@@ -65,6 +65,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "instruction_stfl", VCPU_STAT(instruction_stfl) },
        { "instruction_tprot", VCPU_STAT(instruction_tprot) },
        { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
+       { "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) },
        { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
        { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
        { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
@@ -127,6 +128,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        switch (ext) {
        case KVM_CAP_S390_PSW:
        case KVM_CAP_S390_GMAP:
+       case KVM_CAP_SYNC_MMU:
                r = 1;
                break;
        default:
@@ -270,10 +272,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        restore_fp_regs(&vcpu->arch.guest_fpregs);
        restore_access_regs(vcpu->arch.guest_acrs);
        gmap_enable(vcpu->arch.gmap);
+       atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
+       atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        gmap_disable(vcpu->arch.gmap);
        save_fp_regs(&vcpu->arch.guest_fpregs);
        save_access_regs(vcpu->arch.guest_acrs);
@@ -301,7 +305,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-       atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
+       atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
+                                                   CPUSTAT_SM |
+                                                   CPUSTAT_STOPPED);
        vcpu->arch.sie_block->ecb   = 6;
        vcpu->arch.sie_block->eca   = 0xC1002001U;
        vcpu->arch.sie_block->fac   = (int) (long) facilities;
@@ -428,7 +434,7 @@ static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
 {
        int rc = 0;
 
-       if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
+       if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
                rc = -EBUSY;
        else {
                vcpu->run->psw_mask = psw.mask;
@@ -501,7 +507,7 @@ rerun_vcpu:
        if (vcpu->sigset_active)
                sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
-       atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+       atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 
        BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
 
index 391626361084e363cfd2f0f4251dd652ebc16a58..d02638959922aba41712d16d6dfb20f86f87ec8b 100644 (file)
@@ -336,6 +336,7 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
        u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
        u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
        struct vm_area_struct *vma;
+       unsigned long user_address;
 
        vcpu->stat.instruction_tprot++;
 
@@ -349,9 +350,14 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
                return -EOPNOTSUPP;
 
 
+       /* we must resolve the address without holding the mmap semaphore.
+        * This is ok since the userspace hypervisor is not supposed to change
+        * the mapping while the guest queries the memory. Otherwise the guest
+        * might crash or get wrong info anyway. */
+       user_address = (unsigned long) __guestaddr_to_user(vcpu, address1);
+
        down_read(&current->mm->mmap_sem);
-       vma = find_vma(current->mm,
-                       (unsigned long) __guestaddr_to_user(vcpu, address1));
+       vma = find_vma(current->mm, user_address);
        if (!vma) {
                up_read(&current->mm->mmap_sem);
                return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
index f815118835f3c3221932c5e01c86847cc1ec9ba8..0a7941d74bc68b30b9121090aeb96111c86058b7 100644 (file)
 #define SIGP_SET_PREFIX        0x0d
 #define SIGP_STORE_STATUS_ADDR 0x0e
 #define SIGP_SET_ARCH          0x12
+#define SIGP_SENSE_RUNNING     0x15
 
 /* cpu status bits */
 #define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
+#define SIGP_STAT_NOT_RUNNING      0x00000400UL
 #define SIGP_STAT_INCORRECT_STATE   0x00000200UL
 #define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
 #define SIGP_STAT_EXT_CALL_PENDING  0x00000080UL
@@ -57,8 +59,8 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
        spin_lock(&fi->lock);
        if (fi->local_int[cpu_addr] == NULL)
                rc = 3; /* not operational */
-       else if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
-                & CPUSTAT_RUNNING) {
+       else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags)
+                 & CPUSTAT_STOPPED)) {
                *reg &= 0xffffffff00000000UL;
                rc = 1; /* status stored */
        } else {
@@ -251,7 +253,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
 
        spin_lock_bh(&li->lock);
        /* cpu must be in stopped state */
-       if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
+       if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
                rc = 1; /* incorrect state */
                *reg &= SIGP_STAT_INCORRECT_STATE;
                kfree(inti);
@@ -275,6 +277,38 @@ out_fi:
        return rc;
 }
 
+static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
+                               unsigned long *reg)
+{
+       int rc;
+       struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+
+       if (cpu_addr >= KVM_MAX_VCPUS)
+               return 3; /* not operational */
+
+       spin_lock(&fi->lock);
+       if (fi->local_int[cpu_addr] == NULL)
+               rc = 3; /* not operational */
+       else {
+               if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
+                   & CPUSTAT_RUNNING) {
+                       /* running */
+                       rc = 1;
+               } else {
+                       /* not running */
+                       *reg &= 0xffffffff00000000UL;
+                       *reg |= SIGP_STAT_NOT_RUNNING;
+                       rc = 0;
+               }
+       }
+       spin_unlock(&fi->lock);
+
+       VCPU_EVENT(vcpu, 4, "sensed running status of cpu %x rc %x", cpu_addr,
+                  rc);
+
+       return rc;
+}
+
 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 {
        int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -331,6 +365,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
                rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
                                       &vcpu->arch.guest_gprs[r1]);
                break;
+       case SIGP_SENSE_RUNNING:
+               vcpu->stat.instruction_sigp_sense_running++;
+               rc = __sigp_sense_running(vcpu, cpu_addr,
+                                         &vcpu->arch.guest_gprs[r1]);
+               break;
        case SIGP_RESTART:
                vcpu->stat.instruction_sigp_restart++;
                /* user space must know about restart */
index 1766def5bc3fc7f4717904313c69b2a7879b6d86..a9a301866b3c1846f37792aa371620e2b3004415 100644 (file)
@@ -587,8 +587,13 @@ static void pfault_interrupt(unsigned int ext_int_code,
                } else {
                        /* Completion interrupt was faster than initial
                         * interrupt. Set pfault_wait to -1 so the initial
-                        * interrupt doesn't put the task to sleep. */
-                       tsk->thread.pfault_wait = -1;
+                        * interrupt doesn't put the task to sleep.
+                        * If the task is not running, ignore the completion
+                        * interrupt since it must be a leftover of a PFAULT
+                        * CANCEL operation which didn't remove all pending
+                        * completion interrupts. */
+                       if (tsk->state == TASK_RUNNING)
+                               tsk->thread.pfault_wait = -1;
                }
                put_task_struct(tsk);
        } else {
index 0dca9a5c6be6f91b9a800b2f9bcca7fcf1f6e1fe..15d970328f717c929d25287a09b14af181e23d9c 100644 (file)
@@ -151,8 +151,13 @@ typedef struct page *pgtable_t;
 #endif /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_UNCACHED_MAPPING
+#if defined(CONFIG_29BIT)
+#define UNCAC_ADDR(addr)       P2SEGADDR(addr)
+#define CAC_ADDR(addr)         P1SEGADDR(addr)
+#else
 #define UNCAC_ADDR(addr)       ((addr) - PAGE_OFFSET + uncached_start)
 #define CAC_ADDR(addr)         ((addr) - uncached_start + PAGE_OFFSET)
+#endif
 #else
 #define UNCAC_ADDR(addr)       ((addr))
 #define CAC_ADDR(addr)         ((addr))
index 3432008d28880d360d6764a04fb257c86f291505..152b8627a18440b4c54954a8c652edb59ff9bb1c 100644 (file)
 #define __NR_syncfs            362
 #define __NR_sendmmsg          363
 #define __NR_setns             364
+#define __NR_process_vm_readv  365
+#define __NR_process_vm_writev 366
 
-#define NR_syscalls 365
+#define NR_syscalls 367
 
 #ifdef __KERNEL__
 
index ec9898665f23fbbb2f1da713a5f875dd677ee5c2..c330c23db5a0675283b6ed0df52ef4e381ef0343 100644 (file)
 #define __NR_syncfs            373
 #define __NR_sendmmsg          374
 #define __NR_setns             375
+#define __NR_process_vm_readv  376
+#define __NR_process_vm_writev 377
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 376
+#define NR_syscalls 378
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index a43124e608c3719b52501c56553c69651a0cd698..0bd744f9a3b7051c966266b47f13172bb0d4b4a6 100644 (file)
@@ -176,10 +176,12 @@ static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups,
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xfffe8000,
        .flags          = UPF_BOOT_AUTOCONF,
-       .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+       .scscr          = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+                         SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           =  { 192, 192, 192, 192 },
+       .regtype        = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -193,10 +195,12 @@ static struct platform_device scif0_device = {
 static struct plat_sci_port scif1_platform_data = {
        .mapbase        = 0xfffe8800,
        .flags          = UPF_BOOT_AUTOCONF,
-       .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+       .scscr          = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+                         SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           =  { 196, 196, 196, 196 },
+       .regtype        = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -210,10 +214,12 @@ static struct platform_device scif1_device = {
 static struct plat_sci_port scif2_platform_data = {
        .mapbase        = 0xfffe9000,
        .flags          = UPF_BOOT_AUTOCONF,
-       .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+       .scscr          = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+                         SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           =  { 200, 200, 200, 200 },
+       .regtype        = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -227,10 +233,12 @@ static struct platform_device scif2_device = {
 static struct plat_sci_port scif3_platform_data = {
        .mapbase        = 0xfffe9800,
        .flags          = UPF_BOOT_AUTOCONF,
-       .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+       .scscr          = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+                         SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           =  { 204, 204, 204, 204 },
+       .regtype        = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif3_device = {
index 7d98f909a8acf2e70b9f25a8ce046fdac80074bd..1cc257c9b1e311b806ed2defaa36b6db9ea5c920 100644 (file)
@@ -26,11 +26,12 @@ static unsigned long cpuidle_mode[] = {
 };
 
 static int cpuidle_sleep_enter(struct cpuidle_device *dev,
-                              struct cpuidle_state *state)
+                               struct cpuidle_driver *drv,
+                               int index)
 {
        unsigned long allowed_mode = arch_hwblk_sleep_mode();
        ktime_t before, after;
-       int requested_state = state - &dev->states[0];
+       int requested_state = index;
        int allowed_state;
        int k;
 
@@ -47,11 +48,13 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
         */
        k = min_t(int, allowed_state, requested_state);
 
-       dev->last_state = &dev->states[k];
        before = ktime_get();
        sh_mobile_call_standby(cpuidle_mode[k]);
        after = ktime_get();
-       return ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+       dev->last_residency = (int)ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+       return k;
 }
 
 static struct cpuidle_device cpuidle_dev;
@@ -63,19 +66,19 @@ static struct cpuidle_driver cpuidle_driver = {
 void sh_mobile_setup_cpuidle(void)
 {
        struct cpuidle_device *dev = &cpuidle_dev;
+       struct cpuidle_driver *drv = &cpuidle_driver;
        struct cpuidle_state *state;
        int i;
 
-       cpuidle_register_driver(&cpuidle_driver);
 
        for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-               dev->states[i].name[0] = '\0';
-               dev->states[i].desc[0] = '\0';
+               drv->states[i].name[0] = '\0';
+               drv->states[i].desc[0] = '\0';
        }
 
        i = CPUIDLE_DRIVER_STATE_START;
 
-       state = &dev->states[i++];
+       state = &drv->states[i++];
        snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
        strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
        state->exit_latency = 1;
@@ -85,10 +88,10 @@ void sh_mobile_setup_cpuidle(void)
        state->flags |= CPUIDLE_FLAG_TIME_VALID;
        state->enter = cpuidle_sleep_enter;
 
-       dev->safe_state = state;
+       drv->safe_state_index = i-1;
 
        if (sh_mobile_sleep_supported & SUSP_SH_SF) {
-               state = &dev->states[i++];
+               state = &drv->states[i++];
                snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
                strncpy(state->desc, "SuperH Sleep Mode [SF]",
                        CPUIDLE_DESC_LEN);
@@ -101,7 +104,7 @@ void sh_mobile_setup_cpuidle(void)
        }
 
        if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
-               state = &dev->states[i++];
+               state = &drv->states[i++];
                snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
                strncpy(state->desc, "SuperH Mobile Standby Mode [SF]",
                        CPUIDLE_DESC_LEN);
@@ -113,7 +116,10 @@ void sh_mobile_setup_cpuidle(void)
                state->enter = cpuidle_sleep_enter;
        }
 
+       drv->state_count = i;
        dev->state_count = i;
 
+       cpuidle_register_driver(&cpuidle_driver);
+
        cpuidle_register_device(dev);
 }
index 293e39c59c00522c08e99a9877fcafc36836152b..ee56a9b1a981679a6968d89f232729f4f8ed012f 100644 (file)
@@ -382,3 +382,5 @@ ENTRY(sys_call_table)
        .long sys_syncfs
        .long sys_sendmmsg
        .long sys_setns
+       .long sys_process_vm_readv      /* 365 */
+       .long sys_process_vm_writev
index ceb34b94afa9cb08c6f396cbd29c84d937375c2d..9af7de26fb7153ac1dffca0aedc32a822e1cde5e 100644 (file)
@@ -402,3 +402,5 @@ sys_call_table:
        .long sys_syncfs
        .long sys_sendmmsg
        .long sys_setns                 /* 375 */
+       .long sys_process_vm_readv
+       .long sys_process_vm_writev
index 5b31a8e89823699fbe5f99ebf6eb8d34bac8cb46..a790cc657476320831f9753ad0fd2aff9264ca0a 100644 (file)
@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_bitmap;
 #define kern_addr_valid(addr) \
        (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
 
-extern int io_remap_pfn_range(struct vm_area_struct *vma,
-                             unsigned long from, unsigned long pfn,
-                             unsigned long size, pgprot_t prot);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma,
 #define GET_IOSPACE(pfn)               (pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)                   (pfn & 0x0fffffffUL)
 
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+                          unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+                                    unsigned long from, unsigned long pfn,
+                                    unsigned long size, pgprot_t prot)
+{
+       unsigned long long offset, space, phys_base;
+
+       offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
+       space = GET_IOSPACE(pfn);
+       phys_base = offset | (space << 32ULL);
+
+       return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
 ({                                                                       \
index adf89329af59a653f8694f05df291f2c91475506..38ebb2c601374a386192c061b50ea171c4f83373 100644 (file)
@@ -757,10 +757,6 @@ static inline bool kern_addr_valid(unsigned long addr)
 
 extern int page_in_phys_avail(unsigned long paddr);
 
-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-                              unsigned long pfn,
-                              unsigned long size, pgprot_t prot);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -769,6 +765,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
 #define GET_IOSPACE(pfn)               (pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)                   (pfn & 0x0fffffffffffffffUL)
 
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+                          unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+                                    unsigned long from, unsigned long pfn,
+                                    unsigned long size, pgprot_t prot)
+{
+       unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+       int space = GET_IOSPACE(pfn);
+       unsigned long phys_base;
+
+       phys_base = offset | (((unsigned long) space) << 32UL);
+
+       return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
 #include <asm-generic/pgtable.h>
 
 /* We provide our own get_unmapped_area to cope with VA holes and
index 6260d5deeabca0a009526078a87d1628d960f905..c7cb0af0eb59cb6dfb8a94e6c6fcdd330a7af29d 100644 (file)
 #define __NR_syncfs            335
 #define __NR_sendmmsg          336
 #define __NR_setns             337
+#define __NR_process_vm_readv  338
+#define __NR_process_vm_writev 339
 
-#define NR_syscalls            338
+#define NR_syscalls            340
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
index e27f8ea8656e3e4b9b1c799a6d170cc9739e2cb2..0c218e4c0881fba70c1748e6a4c295e0db280652 100644 (file)
@@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 
 #else /* CONFIG_SPARC32 */
+
+#include <asm/trap_block.h>
+
 struct popc_3insn_patch_entry {
        unsigned int    addr;
        unsigned int    insns[3];
@@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __popc_6insn_patch,
        __popc_6insn_patch_end;
 
 extern void __init per_cpu_patch(void);
+extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
+                                   struct sun4v_1insn_patch_entry *);
+extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
+                                   struct sun4v_2insn_patch_entry *);
 extern void __init sun4v_patch(void);
 extern void __init boot_cpu_id_too_large(int cpu);
 extern unsigned int dcache_parity_tl1_occurred;
index da0c6c70ccb2c0a783043c151bd82d3dc289d86a..e5519870c3d9ab43b516c5994568af974664d616 100644 (file)
@@ -17,6 +17,8 @@
 #include <asm/processor.h>
 #include <asm/spitfire.h>
 
+#include "entry.h"
+
 #ifdef CONFIG_SPARC64
 
 #include <linux/jump_label.h>
@@ -203,6 +205,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
 }
 
 #ifdef CONFIG_SPARC64
+static void do_patch_sections(const Elf_Ehdr *hdr,
+                             const Elf_Shdr *sechdrs)
+{
+       const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
+       char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+       for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+               if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
+                       sun4v_1insn = s;
+               if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
+                       sun4v_2insn = s;
+       }
+
+       if (sun4v_1insn && tlb_type == hypervisor) {
+               void *p = (void *) sun4v_1insn->sh_addr;
+               sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
+       }
+       if (sun4v_2insn && tlb_type == hypervisor) {
+               void *p = (void *) sun4v_2insn->sh_addr;
+               sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
+       }
+}
+
 int module_finalize(const Elf_Ehdr *hdr,
                    const Elf_Shdr *sechdrs,
                    struct module *me)
@@ -210,6 +235,8 @@ int module_finalize(const Elf_Ehdr *hdr,
        /* make jump label nops */
        jump_label_apply_nops(me);
 
+       do_patch_sections(hdr, sechdrs);
+
        /* Cheetah's I-cache is fully coherent.  */
        if (tlb_type == spitfire) {
                unsigned long va;
index c965595aa7e968c8a28e0cfce8f8cd9158db3e0f..a854a1c240ffe1eff016a3324ecfccd1dd63ce4c 100644 (file)
@@ -234,40 +234,50 @@ void __init per_cpu_patch(void)
        }
 }
 
-void __init sun4v_patch(void)
+void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
+                            struct sun4v_1insn_patch_entry *end)
 {
-       extern void sun4v_hvapi_init(void);
-       struct sun4v_1insn_patch_entry *p1;
-       struct sun4v_2insn_patch_entry *p2;
-
-       if (tlb_type != hypervisor)
-               return;
+       while (start < end) {
+               unsigned long addr = start->addr;
 
-       p1 = &__sun4v_1insn_patch;
-       while (p1 < &__sun4v_1insn_patch_end) {
-               unsigned long addr = p1->addr;
-
-               *(unsigned int *) (addr +  0) = p1->insn;
+               *(unsigned int *) (addr +  0) = start->insn;
                wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
 
-               p1++;
+               start++;
        }
+}
 
-       p2 = &__sun4v_2insn_patch;
-       while (p2 < &__sun4v_2insn_patch_end) {
-               unsigned long addr = p2->addr;
+void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
+                            struct sun4v_2insn_patch_entry *end)
+{
+       while (start < end) {
+               unsigned long addr = start->addr;
 
-               *(unsigned int *) (addr +  0) = p2->insns[0];
+               *(unsigned int *) (addr +  0) = start->insns[0];
                wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
 
-               *(unsigned int *) (addr +  4) = p2->insns[1];
+               *(unsigned int *) (addr +  4) = start->insns[1];
                wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  4));
 
-               p2++;
+               start++;
        }
+}
+
+void __init sun4v_patch(void)
+{
+       extern void sun4v_hvapi_init(void);
+
+       if (tlb_type != hypervisor)
+               return;
+
+       sun4v_patch_1insn_range(&__sun4v_1insn_patch,
+                               &__sun4v_1insn_patch_end);
+
+       sun4v_patch_2insn_range(&__sun4v_2insn_patch,
+                               &__sun4v_2insn_patch_end);
 
        sun4v_hvapi_init();
 }
index 2caa556db86dc44818521233c5ba7aad226ca186..023b8860dc9704330391b1db6a8eaf2ea117d32e 100644 (file)
@@ -822,21 +822,23 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-void do_signal32(sigset_t *oldset, struct pt_regs * regs,
-                int restart_syscall, unsigned long orig_i0)
+void do_signal32(sigset_t *oldset, struct pt_regs * regs)
 {
        struct k_sigaction ka;
+       unsigned long orig_i0;
+       int restart_syscall;
        siginfo_t info;
        int signr;
        
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-       /* If the debugger messes with the program counter, it clears
-        * the "in syscall" bit, directing us to not perform a syscall
-        * restart.
-        */
-       if (restart_syscall && !pt_regs_is_syscall(regs))
-               restart_syscall = 0;
+       restart_syscall = 0;
+       orig_i0 = 0;
+       if (pt_regs_is_syscall(regs) &&
+           (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+               restart_syscall = 1;
+               orig_i0 = regs->u_regs[UREG_G6];
+       }
 
        if (signr > 0) {
                if (restart_syscall)
index 8ce247ac04cc0d905abd7d7e1d5de20073ce654a..d54c6e53aba00323fda9f01c95aae0f001352fb9 100644 (file)
@@ -519,10 +519,26 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        siginfo_t info;
        int signr;
 
+       /* It's a lot of work and synchronization to add a new ptrace
+        * register for GDB to save and restore in order to get
+        * orig_i0 correct for syscall restarts when debugging.
+        *
+        * Although it should be the case that most of the global
+        * registers are volatile across a system call, glibc already
+        * depends upon that fact that we preserve them.  So we can't
+        * just use any global register to save away the orig_i0 value.
+        *
+        * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+        * preserved across a system call trap by various pieces of
+        * code in glibc.
+        *
+        * %g7 is used as the "thread register".   %g6 is not used in
+        * any fixed manner.  %g6 is used as a scratch register and
+        * a compiler temporary, but it's value is never used across
+        * a system call.  Therefore %g6 is usable for orig_i0 storage.
+        */
        if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
-               restart_syscall = 1;
-       else
-               restart_syscall = 0;
+               regs->u_regs[UREG_G6] = orig_i0;
 
        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                oldset = &current->saved_sigmask;
@@ -535,8 +551,12 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
         * the software "in syscall" bit, directing us to not perform
         * a syscall restart.
         */
-       if (restart_syscall && !pt_regs_is_syscall(regs))
-               restart_syscall = 0;
+       restart_syscall = 0;
+       if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
+               restart_syscall = 1;
+               orig_i0 = regs->u_regs[UREG_G6];
+       }
+
 
        if (signr > 0) {
                if (restart_syscall)
index a2b81598d90562695abefa70b8c66ea11832341c..f0836cd0e2f243ffb3c1df37ff02cc31488850b7 100644 (file)
@@ -529,11 +529,27 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        siginfo_t info;
        int signr;
        
+       /* It's a lot of work and synchronization to add a new ptrace
+        * register for GDB to save and restore in order to get
+        * orig_i0 correct for syscall restarts when debugging.
+        *
+        * Although it should be the case that most of the global
+        * registers are volatile across a system call, glibc already
+        * depends upon that fact that we preserve them.  So we can't
+        * just use any global register to save away the orig_i0 value.
+        *
+        * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+        * preserved across a system call trap by various pieces of
+        * code in glibc.
+        *
+        * %g7 is used as the "thread register".   %g6 is not used in
+        * any fixed manner.  %g6 is used as a scratch register and
+        * a compiler temporary, but it's value is never used across
+        * a system call.  Therefore %g6 is usable for orig_i0 storage.
+        */
        if (pt_regs_is_syscall(regs) &&
-           (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
-               restart_syscall = 1;
-       } else
-               restart_syscall = 0;
+           (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
+               regs->u_regs[UREG_G6] = orig_i0;
 
        if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
@@ -542,22 +558,20 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
 
 #ifdef CONFIG_COMPAT
        if (test_thread_flag(TIF_32BIT)) {
-               extern void do_signal32(sigset_t *, struct pt_regs *,
-                                       int restart_syscall,
-                                       unsigned long orig_i0);
-               do_signal32(oldset, regs, restart_syscall, orig_i0);
+               extern void do_signal32(sigset_t *, struct pt_regs *);
+               do_signal32(oldset, regs);
                return;
        }
 #endif 
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-       /* If the debugger messes with the program counter, it clears
-        * the software "in syscall" bit, directing us to not perform
-        * a syscall restart.
-        */
-       if (restart_syscall && !pt_regs_is_syscall(regs))
-               restart_syscall = 0;
+       restart_syscall = 0;
+       if (pt_regs_is_syscall(regs) &&
+           (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+               restart_syscall = 1;
+               orig_i0 = regs->u_regs[UREG_G6];
+       }
 
        if (signr > 0) {
                if (restart_syscall)
index e7dc508c38eb47dd1f77bee9a125687287c2856a..b19570d41a39eab11e7b60d2146aec678d0c8621 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/types.h>
 #include <linux/thread_info.h>
 #include <linux/uaccess.h>
+#include <linux/errno.h>
 
 #include <asm/sigcontext.h>
 #include <asm/fpumacro.h>
index 09d8ec454450bcfcbfa3ef7e041305c5fe1a7501..63402f9e9f51f75622f9132e0b8f5372bcc806c1 100644 (file)
@@ -84,4 +84,4 @@ sys_call_table:
 /*320*/        .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
 /*325*/        .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
-/*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns
+/*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
index edbec45d46884c9e1d33ab92be65119f0137369d..db86b1a0e9a9ff8a8e8129a88cd32982288e0ad3 100644 (file)
@@ -85,7 +85,7 @@ sys_call_table32:
 /*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
        .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
-       .word sys_syncfs, compat_sys_sendmmsg, sys_setns
+       .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
 
 #endif /* CONFIG_COMPAT */
 
@@ -162,4 +162,4 @@ sys_call_table:
 /*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
        .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
-       .word sys_syncfs, sys_sendmmsg, sys_setns
+       .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
index e3cda21b5ee994200b7d09e7e14c33704363e67c..301421c11291c6a0c8ef01a1af18da17453c9d35 100644 (file)
@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64)   += ultra.o tlb.o tsb.o gup.o
 obj-y                   += fault_$(BITS).o
 obj-y                   += init_$(BITS).o
 obj-$(CONFIG_SPARC32)   += loadmmu.o
-obj-y                   += generic_$(BITS).o
 obj-$(CONFIG_SPARC32)   += extable.o btfixup.o srmmu.o iommu.o io-unit.o
 obj-$(CONFIG_SPARC32)   += hypersparc.o viking.o tsunami.o swift.o
 obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c
deleted file mode 100644 (file)
index 6ca39a6..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- *            MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-#include <linux/export.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
-       unsigned long offset, pgprot_t prot, int space)
-{
-       unsigned long end;
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       do {
-               set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
-               address += PAGE_SIZE;
-               offset += PAGE_SIZE;
-               pte++;
-       } while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-       unsigned long offset, pgprot_t prot, int space)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       offset -= address;
-       do {
-               pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address < end);
-       return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-                      unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-       int error = 0;
-       pgd_t * dir;
-       unsigned long beg = from;
-       unsigned long end = from + size;
-       struct mm_struct *mm = vma->vm_mm;
-       int space = GET_IOSPACE(pfn);
-       unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-
-       /* See comment in mm/memory.c remap_pfn_range */
-       vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-       vma->vm_pgoff = (offset >> PAGE_SHIFT) |
-               ((unsigned long)space << 28UL);
-
-       offset -= from;
-       dir = pgd_offset(mm, from);
-       flush_cache_range(vma, beg, end);
-
-       while (from < end) {
-               pmd_t *pmd = pmd_alloc(mm, dir, from);
-               error = -ENOMEM;
-               if (!pmd)
-                       break;
-               error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
-               if (error)
-                       break;
-               from = (from + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       }
-
-       flush_tlb_range(vma, beg, end);
-       return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c
deleted file mode 100644 (file)
index 9b357dd..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- *            MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/export.h>
-#include <linux/pagemap.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
-                                     unsigned long address,
-                                     unsigned long size,
-                                     unsigned long offset, pgprot_t prot,
-                                     int space)
-{
-       unsigned long end;
-
-       /* clear hack bit that was used as a write_combine side-effect flag */
-       offset &= ~0x1UL;
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       do {
-               pte_t entry;
-               unsigned long curend = address + PAGE_SIZE;
-               
-               entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
-               if (!(address & 0xffff)) {
-                       if (PAGE_SIZE < (4 * 1024 * 1024) &&
-                           !(address & 0x3fffff) &&
-                           !(offset & 0x3ffffe) &&
-                           end >= address + 0x400000) {
-                               entry = mk_pte_io(offset, prot, space,
-                                                 4 * 1024 * 1024);
-                               curend = address + 0x400000;
-                               offset += 0x400000;
-                       } else if (PAGE_SIZE < (512 * 1024) &&
-                                  !(address & 0x7ffff) &&
-                                  !(offset & 0x7fffe) &&
-                                  end >= address + 0x80000) {
-                               entry = mk_pte_io(offset, prot, space,
-                                                 512 * 1024 * 1024);
-                               curend = address + 0x80000;
-                               offset += 0x80000;
-                       } else if (PAGE_SIZE < (64 * 1024) &&
-                                  !(offset & 0xfffe) &&
-                                  end >= address + 0x10000) {
-                               entry = mk_pte_io(offset, prot, space,
-                                                 64 * 1024);
-                               curend = address + 0x10000;
-                               offset += 0x10000;
-                       } else
-                               offset += PAGE_SIZE;
-               } else
-                       offset += PAGE_SIZE;
-
-               if (pte_write(entry))
-                       entry = pte_mkdirty(entry);
-               do {
-                       BUG_ON(!pte_none(*pte));
-                       set_pte_at(mm, address, pte, entry);
-                       address += PAGE_SIZE;
-                       pte_val(entry) += PAGE_SIZE;
-                       pte++;
-               } while (address < curend);
-       } while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-       unsigned long offset, pgprot_t prot, int space)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       offset -= address;
-       do {
-               pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
-               pte_unmap(pte);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address < end);
-       return 0;
-}
-
-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
-       unsigned long offset, pgprot_t prot, int space)
-{
-       unsigned long end;
-
-       address &= ~PUD_MASK;
-       end = address + size;
-       if (end > PUD_SIZE)
-               end = PUD_SIZE;
-       offset -= address;
-       do {
-               pmd_t *pmd = pmd_alloc(mm, pud, address);
-               if (!pud)
-                       return -ENOMEM;
-               io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
-               address = (address + PUD_SIZE) & PUD_MASK;
-               pud++;
-       } while (address < end);
-       return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-               unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-       int error = 0;
-       pgd_t * dir;
-       unsigned long beg = from;
-       unsigned long end = from + size;
-       struct mm_struct *mm = vma->vm_mm;
-       int space = GET_IOSPACE(pfn);
-       unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-       unsigned long phys_base;
-
-       phys_base = offset | (((unsigned long) space) << 32UL);
-
-       /* See comment in mm/memory.c remap_pfn_range */
-       vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-       vma->vm_pgoff = phys_base >> PAGE_SHIFT;
-
-       offset -= from;
-       dir = pgd_offset(mm, from);
-       flush_cache_range(vma, beg, end);
-
-       while (from < end) {
-               pud_t *pud = pud_alloc(mm, dir, from);
-               error = -ENOMEM;
-               if (!pud)
-                       break;
-               error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
-               if (error)
-                       break;
-               from = (from + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       }
-
-       flush_tlb_range(vma, beg, end);
-       return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
index e57dcce9bfda4da6ea6be362a542bf891289f0c0..942ed6174f1d073e565d52e5dc074c7e84d3b533 100644 (file)
@@ -237,13 +237,13 @@ menu "PKUnity NetBook-0916 Features"
 
 config I2C_BATTERY_BQ27200
        tristate "I2C Battery BQ27200 Support"
-       select PUV3_I2C
+       select I2C_PUV3
        select POWER_SUPPLY
        select BATTERY_BQ27x00
 
 config I2C_EEPROM_AT24
        tristate "I2C EEPROMs AT24 support"
-       select PUV3_I2C
+       select I2C_PUV3
        select MISC_DEVICES
        select EEPROM_AT24
 
index ae2ec334c3c61473ffa6b7b5cf8695c8d64c322b..1a36262398435ff9f9f224cab74da1a3d2bb0233 100644 (file)
@@ -44,18 +44,4 @@ config DEBUG_OCD
          Say Y here if you want the debug print routines to direct their
          output to the UniCore On-Chip-Debugger channel using CP #1.
 
-config DEBUG_OCD_BREAKPOINT
-       bool "Breakpoint support via On-Chip-Debugger"
-       depends on DEBUG_OCD
-
-config DEBUG_UART
-       int "Kernel low-level debugging messages via serial port"
-       depends on DEBUG_LL
-       range 0 1
-       default "0"
-       help
-         Choice for UART for kernel low-level using PKUnity UARTS,
-         should be between zero and one. The port must have been
-         initialised by the boot-loader before use.
-
 endmenu
index b0954a2d23cfaf5b4db0bbe1b6e95493d75ebc03..950a9afa38f8632239df166ac21ffe094229217e 100644 (file)
@@ -10,8 +10,8 @@
 # Copyright (C) 2001~2010 GUAN Xue-tao
 #
 
-EXTRA_CFLAGS   := -fpic -fno-builtin
-EXTRA_AFLAGS   := -Wa,-march=all
+ccflags-y      := -fpic -fno-builtin
+asflags-y      := -Wa,-march=all
 
 OBJS           := misc.o
 
index 1628a63289946218c12cebed99246c87087e8a18..401f597bc38cfcdf102ff6188f8bd3c27f46dde5 100644 (file)
 #ifndef __UNICORE_BITOPS_H__
 #define __UNICORE_BITOPS_H__
 
-#define find_next_bit          __uc32_find_next_bit
-#define find_next_zero_bit     __uc32_find_next_zero_bit
-
-#define find_first_bit         __uc32_find_first_bit
-#define find_first_zero_bit    __uc32_find_first_zero_bit
-
 #define _ASM_GENERIC_BITOPS_FLS_H_
 #define _ASM_GENERIC_BITOPS___FLS_H_
 #define _ASM_GENERIC_BITOPS_FFS_H_
@@ -44,4 +38,10 @@ static inline int fls(int x)
 
 #include <asm-generic/bitops.h>
 
+/* following definitions: to avoid using codes in lib/find_*.c */
+#define find_next_bit          find_next_bit
+#define find_next_zero_bit     find_next_zero_bit
+#define find_first_bit         find_first_bit
+#define find_first_zero_bit    find_first_zero_bit
+
 #endif /* __UNICORE_BITOPS_H__ */
index e11cb07865782c81b82e4dd90d1977b8f4495245..f0d780a51f9b5dec74a5310fe0f1fd2c4fdc7b28 100644 (file)
@@ -53,7 +53,6 @@ struct thread_struct {
 #define start_thread(regs, pc, sp)                                     \
 ({                                                                     \
        unsigned long *stack = (unsigned long *)sp;                     \
-       set_fs(USER_DS);                                                \
        memset(regs->uregs, 0, sizeof(regs->uregs));                    \
        regs->UCreg_asr = USER_MODE;                                    \
        regs->UCreg_pc = pc & ~1;       /* pc */                        \
index a8970809428a65985873e42ffd417782c0f47ae9..d98bd812cae1ea17efcb314a1cccee9639636b37 100644 (file)
@@ -24,8 +24,8 @@
 
 #include "ksyms.h"
 
-EXPORT_SYMBOL(__uc32_find_next_zero_bit);
-EXPORT_SYMBOL(__uc32_find_next_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
+EXPORT_SYMBOL(find_next_bit);
 
 EXPORT_SYMBOL(__backtrace);
 
index c360ce905d8b7bcb0d9b84b796089987c5cf967b..c77746247d3698856f26e27531c7454382178a6e 100644 (file)
@@ -17,7 +17,7 @@
  * Purpose  : Find a 'zero' bit
  * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
  */
-__uc32_find_first_zero_bit:
+ENTRY(find_first_zero_bit)
                cxor.a  r1, #0
                beq     3f
                mov     r2, #0
@@ -29,13 +29,14 @@ __uc32_find_first_zero_bit:
                bub     1b
 3:             mov     r0, r1                  @ no free bits
                mov     pc, lr
+ENDPROC(find_first_zero_bit)
 
 /*
  * Purpose  : Find next 'zero' bit
  * Prototype: int find_next_zero_bit
  *             (void *addr, unsigned int maxbit, int offset)
  */
-ENTRY(__uc32_find_next_zero_bit)
+ENTRY(find_next_zero_bit)
                cxor.a  r1, #0
                beq     3b
                and.a   ip, r2, #7
@@ -47,14 +48,14 @@ ENTRY(__uc32_find_next_zero_bit)
                or      r2, r2, #7              @ if zero, then no bits here
                add     r2, r2, #1              @ align bit pointer
                b       2b                      @ loop for next bit
-ENDPROC(__uc32_find_next_zero_bit)
+ENDPROC(find_next_zero_bit)
 
 /*
  * Purpose  : Find a 'one' bit
  * Prototype: int find_first_bit
  *             (const unsigned long *addr, unsigned int maxbit);
  */
-__uc32_find_first_bit:
+ENTRY(find_first_bit)
                cxor.a  r1, #0
                beq     3f
                mov     r2, #0
@@ -66,13 +67,14 @@ __uc32_find_first_bit:
                bub     1b
 3:             mov     r0, r1                  @ no free bits
                mov     pc, lr
+ENDPROC(find_first_bit)
 
 /*
  * Purpose  : Find next 'one' bit
  * Prototype: int find_next_zero_bit
  *             (void *addr, unsigned int maxbit, int offset)
  */
-ENTRY(__uc32_find_next_bit)
+ENTRY(find_next_bit)
                cxor.a  r1, #0
                beq     3b
                and.a   ip, r2, #7
@@ -83,7 +85,7 @@ ENTRY(__uc32_find_next_bit)
                or      r2, r2, #7              @ if zero, then no bits here
                add     r2, r2, #1              @ align bit pointer
                b       2b                      @ loop for next bit
-ENDPROC(__uc32_find_next_bit)
+ENDPROC(find_next_bit)
 
 /*
  * One or more bits in the LSB of r3 are assumed to be set.
index 9b7273cb21937e8a884a08b45b3024af1bf3cfbc..1a6c09af048fbd587613c750502677d7cbb1c052 100644 (file)
@@ -49,6 +49,7 @@ extern unsigned int apic_verbosity;
 extern int local_apic_timer_c2_ok;
 
 extern int disable_apic;
+extern unsigned int lapic_timer_frequency;
 
 #ifdef CONFIG_SMP
 extern void __inquire_remote_apic(int apicid);
index 72a8b52e7dfd0de3fa4271284fdd4a76da7fb31b..a01e7ec7d2377aaede271b6ad4ddd546ef5238a5 100644 (file)
@@ -17,7 +17,7 @@
 #define NMI_REASON_CLEAR_IOCHK 0x08
 #define NMI_REASON_CLEAR_MASK  0x0f
 
-static inline unsigned char get_nmi_reason(void)
+static inline unsigned char default_get_nmi_reason(void)
 {
        return inb(NMI_REASON_PORT);
 }
index c9321f34e55b3fa2cdb9fd4afeaa332dac345add..0e8ae57d3656c4576498b545826a5880214fe9e5 100644 (file)
@@ -201,7 +201,10 @@ int mce_notify_irq(void);
 void mce_notify_process(void);
 
 DECLARE_PER_CPU(struct mce, injectm);
-extern struct file_operations mce_chrdev_ops;
+
+extern void register_mce_write_callback(ssize_t (*)(struct file *filp,
+                                   const char __user *ubuf,
+                                   size_t usize, loff_t *off));
 
 /*
  * Exception handler
index 719f00b28ff5358caf87d736ed5b4100dafdce9e..e6283129c821014eba1afcbbb1bdd042b6b73e04 100644 (file)
@@ -44,6 +44,13 @@ enum mrst_timer_options {
 
 extern enum mrst_timer_options mrst_timer_options;
 
+/*
+ * Penwell uses spread spectrum clock, so the freq number is not exactly
+ * the same as reported by MSR based on SDM.
+ */
+#define PENWELL_FSB_FREQ_83SKU         83200
+#define PENWELL_FSB_FREQ_100SKU        99840
+
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX   8
 
index d3d859035af9e1968d0ad9d4a39000331c27c8f1..1971e652d24be5fc0674633c1edb3717645306e7 100644 (file)
@@ -152,6 +152,7 @@ struct x86_cpuinit_ops {
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:             calibrate TSC
+ * @wallclock_init:            init the wallclock device
  * @get_wallclock:             get time from HW clock like RTC etc.
  * @set_wallclock:             set time back to HW clock
  * @is_untracked_pat_range     exclude from PAT logic
@@ -160,11 +161,13 @@ struct x86_cpuinit_ops {
  */
 struct x86_platform_ops {
        unsigned long (*calibrate_tsc)(void);
+       void (*wallclock_init)(void);
        unsigned long (*get_wallclock)(void);
        int (*set_wallclock)(unsigned long nowtime);
        void (*iommu_shutdown)(void);
        bool (*is_untracked_pat_range)(u64 start, u64 end);
        void (*nmi_init)(void);
+       unsigned char (*get_nmi_reason)(void);
        int (*i8042_detect)(void);
 };
 
index c63822816249e8c41fa47643d3204bde8a758a42..1f84794f0759327c387d602cddccb3d479188f92 100644 (file)
@@ -738,5 +738,5 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n)
 
        atomic_set(&stop_machine_first, 1);
        wrote_text = 0;
-       __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+       __stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask);
 }
index a2fd72e0ab35bbff6703836f82540a0f71588e85..f98d84caf94cfdc43cedda4cb411ebea5213e4b7 100644 (file)
@@ -186,7 +186,7 @@ static struct resource lapic_resource = {
        .flags = IORESOURCE_MEM | IORESOURCE_BUSY,
 };
 
-static unsigned int calibration_result;
+unsigned int lapic_timer_frequency = 0;
 
 static void apic_pm_activate(void);
 
@@ -454,7 +454,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
        case CLOCK_EVT_MODE_ONESHOT:
-               __setup_APIC_LVTT(calibration_result,
+               __setup_APIC_LVTT(lapic_timer_frequency,
                                  mode != CLOCK_EVT_MODE_PERIODIC, 1);
                break;
        case CLOCK_EVT_MODE_UNUSED:
@@ -638,6 +638,25 @@ static int __init calibrate_APIC_clock(void)
        long delta, deltatsc;
        int pm_referenced = 0;
 
+       /**
+        * check if lapic timer has already been calibrated by platform
+        * specific routine, such as tsc calibration code. if so, we just fill
+        * in the clockevent structure and return.
+        */
+
+       if (lapic_timer_frequency) {
+               apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
+                               lapic_timer_frequency);
+               lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
+                                       TICK_NSEC, lapic_clockevent.shift);
+               lapic_clockevent.max_delta_ns =
+                       clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+               lapic_clockevent.min_delta_ns =
+                       clockevent_delta2ns(0xF, &lapic_clockevent);
+               lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+               return 0;
+       }
+
        local_irq_disable();
 
        /* Replace the global interrupt handler */
@@ -679,12 +698,12 @@ static int __init calibrate_APIC_clock(void)
        lapic_clockevent.min_delta_ns =
                clockevent_delta2ns(0xF, &lapic_clockevent);
 
-       calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
+       lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
 
        apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
        apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
        apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
-                   calibration_result);
+                   lapic_timer_frequency);
 
        if (cpu_has_tsc) {
                apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
@@ -695,13 +714,13 @@ static int __init calibrate_APIC_clock(void)
 
        apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
                    "%u.%04u MHz.\n",
-                   calibration_result / (1000000 / HZ),
-                   calibration_result % (1000000 / HZ));
+                   lapic_timer_frequency / (1000000 / HZ),
+                   lapic_timer_frequency % (1000000 / HZ));
 
        /*
         * Do a sanity check on the APIC calibration result
         */
-       if (calibration_result < (1000000 / HZ)) {
+       if (lapic_timer_frequency < (1000000 / HZ)) {
                local_irq_enable();
                pr_warning("APIC frequency too slow, disabling apic timer\n");
                return -1;
index 3c31fa98af6dcb23a9298fae4c0ea29495167d0f..6d939d7847e293901538cfe32ae1b95d1d82551a 100644 (file)
@@ -193,10 +193,8 @@ int __init arch_early_irq_init(void)
        struct irq_cfg *cfg;
        int count, node, i;
 
-       if (!legacy_pic->nr_legacy_irqs) {
-               nr_irqs_gsi = 0;
+       if (!legacy_pic->nr_legacy_irqs)
                io_apic_irqs = ~0UL;
-       }
 
        for (i = 0; i < nr_ioapics; i++) {
                ioapics[i].saved_registers =
@@ -1696,6 +1694,7 @@ __apicdebuginit(void) print_IO_APICs(void)
        int ioapic_idx;
        struct irq_cfg *cfg;
        unsigned int irq;
+       struct irq_chip *chip;
 
        printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
        for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
@@ -1716,6 +1715,10 @@ __apicdebuginit(void) print_IO_APICs(void)
        for_each_active_irq(irq) {
                struct irq_pin_list *entry;
 
+               chip = irq_get_chip(irq);
+               if (chip != &ioapic_chip)
+                       continue;
+
                cfg = irq_get_chip_data(irq);
                if (!cfg)
                        continue;
index 6199232161cffa181d6cf80605adb38dfbb51a61..319882ef848d3cd43c0a4dcfa41ea14cd09502ab 100644 (file)
@@ -208,7 +208,7 @@ static int inject_init(void)
        if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
                return -ENOMEM;
        printk(KERN_INFO "Machine check injector initialized\n");
-       mce_chrdev_ops.write = mce_write;
+       register_mce_write_callback(mce_write);
        register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
                                "mce_notify");
        return 0;
index 362056aefeb474c86b165c4f9c77d213b40fdbfa..2af127d4c3d1dc2ebdab3e0e2ff95d2d07595a46 100644 (file)
@@ -1634,16 +1634,35 @@ static long mce_chrdev_ioctl(struct file *f, unsigned int cmd,
        }
 }
 
-/* Modified in mce-inject.c, so not static or const */
-struct file_operations mce_chrdev_ops = {
+static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf,
+                           size_t usize, loff_t *off);
+
+void register_mce_write_callback(ssize_t (*fn)(struct file *filp,
+                            const char __user *ubuf,
+                            size_t usize, loff_t *off))
+{
+       mce_write = fn;
+}
+EXPORT_SYMBOL_GPL(register_mce_write_callback);
+
+ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf,
+                        size_t usize, loff_t *off)
+{
+       if (mce_write)
+               return mce_write(filp, ubuf, usize, off);
+       else
+               return -EINVAL;
+}
+
+static const struct file_operations mce_chrdev_ops = {
        .open                   = mce_chrdev_open,
        .release                = mce_chrdev_release,
        .read                   = mce_chrdev_read,
+       .write                  = mce_chrdev_write,
        .poll                   = mce_chrdev_poll,
        .unlocked_ioctl         = mce_chrdev_ioctl,
        .llseek                 = no_llseek,
 };
-EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
 static struct miscdevice mce_chrdev_device = {
        MISC_MCELOG_MINOR,
index c1a0188e29aef61d22706c8d0f2b99f843cf8fc7..44842d756b29fa9b2705fb8c57189fe5d28b5732 100644 (file)
@@ -74,9 +74,10 @@ static cycle_t kvm_clock_read(void)
        struct pvclock_vcpu_time_info *src;
        cycle_t ret;
 
-       src = &get_cpu_var(hv_clock);
+       preempt_disable_notrace();
+       src = &__get_cpu_var(hv_clock);
        ret = pvclock_clocksource_read(src);
-       put_cpu_var(hv_clock);
+       preempt_enable_notrace();
        return ret;
 }
 
index b9c8628974af3ae4eeb7cc73891140618df589b2..e88f37b58dddeeaecfb8951649db799986b7e247 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/traps.h>
 #include <asm/mach_traps.h>
 #include <asm/nmi.h>
+#include <asm/x86_init.h>
 
 #define NMI_MAX_NAMELEN        16
 struct nmiaction {
@@ -348,7 +349,7 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
 
        /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
        raw_spin_lock(&nmi_reason_lock);
-       reason = get_nmi_reason();
+       reason = x86_platform.get_nmi_reason();
 
        if (reason & NMI_REASON_MASK) {
                if (reason & NMI_REASON_SERR)
index afaf38447ef5fc42c53e78168492fa9eb89a032b..cf0ef986cb6dff51348c17c691491f6f48c61a60 100644 (file)
@@ -1045,6 +1045,8 @@ void __init setup_arch(char **cmdline_p)
 
        x86_init.timers.wallclock_init();
 
+       x86_platform.wallclock_init();
+
        mcheck_init();
 
        arch_init_ideal_nops();
index 6f164bd5e14d167d417b2f86e5fc8580047ed371..c1d6cd549397ad54dbcb32526c9170e1f590a759 100644 (file)
 #include <asm/pat.h>
 #include <asm/tsc.h>
 #include <asm/iommu.h>
+#include <asm/mach_traps.h>
 
 void __cpuinit x86_init_noop(void) { }
 void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
+void wallclock_init_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -97,11 +99,13 @@ static int default_i8042_detect(void) { return 1; };
 
 struct x86_platform_ops x86_platform = {
        .calibrate_tsc                  = native_calibrate_tsc,
+       .wallclock_init                 = wallclock_init_noop,
        .get_wallclock                  = mach_get_cmos_time,
        .set_wallclock                  = mach_set_rtc_mmss,
        .iommu_shutdown                 = iommu_shutdown_noop,
        .is_untracked_pat_range         = is_ISA_range,
        .nmi_init                       = default_nmi_init,
+       .get_nmi_reason                 = default_get_nmi_reason,
        .i8042_detect                   = default_i8042_detect
 };
 
index a0d6bd9ad442f1746bfa66eaabe86641470b7d0f..579a0b51696ac560b1768ae445bb8f2084172f8c 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/mce.h>
 #include <asm/i387.h>
 #include <asm/xcr.h>
+#include <asm/perf_event.h>
 
 #include "trace.h"
 
@@ -118,7 +119,7 @@ module_param(ple_gap, int, S_IRUGO);
 static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
 module_param(ple_window, int, S_IRUGO);
 
-#define NR_AUTOLOAD_MSRS 1
+#define NR_AUTOLOAD_MSRS 8
 #define VMCS02_POOL_SIZE 1
 
 struct vmcs {
@@ -622,6 +623,7 @@ static unsigned long *vmx_msr_bitmap_legacy;
 static unsigned long *vmx_msr_bitmap_longmode;
 
 static bool cpu_has_load_ia32_efer;
+static bool cpu_has_load_perf_global_ctrl;
 
 static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
 static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -1191,15 +1193,34 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
        vmcs_write32(EXCEPTION_BITMAP, eb);
 }
 
+static void clear_atomic_switch_msr_special(unsigned long entry,
+               unsigned long exit)
+{
+       vmcs_clear_bits(VM_ENTRY_CONTROLS, entry);
+       vmcs_clear_bits(VM_EXIT_CONTROLS, exit);
+}
+
 static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
 {
        unsigned i;
        struct msr_autoload *m = &vmx->msr_autoload;
 
-       if (msr == MSR_EFER && cpu_has_load_ia32_efer) {
-               vmcs_clear_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER);
-               vmcs_clear_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER);
-               return;
+       switch (msr) {
+       case MSR_EFER:
+               if (cpu_has_load_ia32_efer) {
+                       clear_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER,
+                                       VM_EXIT_LOAD_IA32_EFER);
+                       return;
+               }
+               break;
+       case MSR_CORE_PERF_GLOBAL_CTRL:
+               if (cpu_has_load_perf_global_ctrl) {
+                       clear_atomic_switch_msr_special(
+                                       VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+                                       VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+                       return;
+               }
+               break;
        }
 
        for (i = 0; i < m->nr; ++i)
@@ -1215,25 +1236,55 @@ static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
        vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
 }
 
+static void add_atomic_switch_msr_special(unsigned long entry,
+               unsigned long exit, unsigned long guest_val_vmcs,
+               unsigned long host_val_vmcs, u64 guest_val, u64 host_val)
+{
+       vmcs_write64(guest_val_vmcs, guest_val);
+       vmcs_write64(host_val_vmcs, host_val);
+       vmcs_set_bits(VM_ENTRY_CONTROLS, entry);
+       vmcs_set_bits(VM_EXIT_CONTROLS, exit);
+}
+
 static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
                                  u64 guest_val, u64 host_val)
 {
        unsigned i;
        struct msr_autoload *m = &vmx->msr_autoload;
 
-       if (msr == MSR_EFER && cpu_has_load_ia32_efer) {
-               vmcs_write64(GUEST_IA32_EFER, guest_val);
-               vmcs_write64(HOST_IA32_EFER, host_val);
-               vmcs_set_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER);
-               vmcs_set_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER);
-               return;
+       switch (msr) {
+       case MSR_EFER:
+               if (cpu_has_load_ia32_efer) {
+                       add_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER,
+                                       VM_EXIT_LOAD_IA32_EFER,
+                                       GUEST_IA32_EFER,
+                                       HOST_IA32_EFER,
+                                       guest_val, host_val);
+                       return;
+               }
+               break;
+       case MSR_CORE_PERF_GLOBAL_CTRL:
+               if (cpu_has_load_perf_global_ctrl) {
+                       add_atomic_switch_msr_special(
+                                       VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+                                       VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL,
+                                       GUEST_IA32_PERF_GLOBAL_CTRL,
+                                       HOST_IA32_PERF_GLOBAL_CTRL,
+                                       guest_val, host_val);
+                       return;
+               }
+               break;
        }
 
        for (i = 0; i < m->nr; ++i)
                if (m->guest[i].index == msr)
                        break;
 
-       if (i == m->nr) {
+       if (i == NR_AUTOLOAD_MSRS) {
+               printk_once(KERN_WARNING"Not enough mst switch entries. "
+                               "Can't add msr %x\n", msr);
+               return;
+       } else if (i == m->nr) {
                ++m->nr;
                vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr);
                vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
@@ -2455,6 +2506,42 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
                && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
                                   VM_EXIT_LOAD_IA32_EFER);
 
+       cpu_has_load_perf_global_ctrl =
+               allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
+                               VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
+               && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
+                                  VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+
+       /*
+        * Some cpus support VM_ENTRY_(LOAD|SAVE)_IA32_PERF_GLOBAL_CTRL
+        * but due to arrata below it can't be used. Workaround is to use
+        * msr load mechanism to switch IA32_PERF_GLOBAL_CTRL.
+        *
+        * VM Exit May Incorrectly Clear IA32_PERF_GLOBAL_CTRL [34:32]
+        *
+        * AAK155             (model 26)
+        * AAP115             (model 30)
+        * AAT100             (model 37)
+        * BC86,AAY89,BD102   (model 44)
+        * BA97               (model 46)
+        *
+        */
+       if (cpu_has_load_perf_global_ctrl && boot_cpu_data.x86 == 0x6) {
+               switch (boot_cpu_data.x86_model) {
+               case 26:
+               case 30:
+               case 37:
+               case 44:
+               case 46:
+                       cpu_has_load_perf_global_ctrl = false;
+                       printk_once(KERN_WARNING"kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
+                                       "does not work properly. Using workaround\n");
+                       break;
+               default:
+                       break;
+               }
+       }
+
        return 0;
 }
 
@@ -5968,6 +6055,24 @@ static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
 }
 
+static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
+{
+       int i, nr_msrs;
+       struct perf_guest_switch_msr *msrs;
+
+       msrs = perf_guest_get_msrs(&nr_msrs);
+
+       if (!msrs)
+               return;
+
+       for (i = 0; i < nr_msrs; i++)
+               if (msrs[i].host == msrs[i].guest)
+                       clear_atomic_switch_msr(vmx, msrs[i].msr);
+               else
+                       add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest,
+                                       msrs[i].host);
+}
+
 #ifdef CONFIG_X86_64
 #define R "r"
 #define Q "q"
@@ -6017,6 +6122,8 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
        if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
                vmx_set_interrupt_shadow(vcpu, 0);
 
+       atomic_switch_perf_msrs(vmx);
+
        vmx->__launched = vmx->loaded_vmcs->launched;
        asm(
                /* Store host registers */
index 28071bb31db7bc1512242589dd10ad5184c976dc..4c61b52191eb293bcaef2cac2380c6114cdaefcf 100644 (file)
@@ -109,7 +109,7 @@ static __init void sdv_serial_fixup(void)
 }
 
 #else
-static inline void sdv_serial_fixup(void);
+static inline void sdv_serial_fixup(void) {};
 #endif
 
 static void __init sdv_arch_setup(void)
index 6ed7afdaf4afa5e194ea75a43c08e84d20c5d915..b1489a06a49dbc5ac0f4acd5eeaddc6136f05c1a 100644 (file)
@@ -187,11 +187,34 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 static unsigned long __init mrst_calibrate_tsc(void)
 {
        unsigned long flags, fast_calibrate;
-
-       local_irq_save(flags);
-       fast_calibrate = apbt_quick_calibrate();
-       local_irq_restore(flags);
-
+       if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
+               u32 lo, hi, ratio, fsb;
+
+               rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+               pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
+               ratio = (hi >> 8) & 0x1f;
+               pr_debug("ratio is %d\n", ratio);
+               if (!ratio) {
+                       pr_err("read a zero ratio, should be incorrect!\n");
+                       pr_err("force tsc ratio to 16 ...\n");
+                       ratio = 16;
+               }
+               rdmsr(MSR_FSB_FREQ, lo, hi);
+               if ((lo & 0x7) == 0x7)
+                       fsb = PENWELL_FSB_FREQ_83SKU;
+               else
+                       fsb = PENWELL_FSB_FREQ_100SKU;
+               fast_calibrate = ratio * fsb;
+               pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+               lapic_timer_frequency = fsb * 1000 / HZ;
+               /* mark tsc clocksource as reliable */
+               set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+       } else {
+               local_irq_save(flags);
+               fast_calibrate = apbt_quick_calibrate();
+               local_irq_restore(flags);
+       }
+       
        if (fast_calibrate)
                return fast_calibrate;
 
@@ -253,6 +276,17 @@ static void mrst_reboot(void)
        intel_scu_ipc_simple_command(0xf1, 0);
 }
 
+/*
+ * Moorestown does not have external NMI source nor port 0x61 to report
+ * NMI status. The possible NMI sources are from pmu as a result of NMI
+ * watchdog or lock debug. Reading io port 0x61 results in 0xff which
+ * misled NMI handler.
+ */
+static unsigned char mrst_get_nmi_reason(void)
+{
+       return 0;
+}
+
 /*
  * Moorestown specific x86_init function overrides and early setup
  * calls.
@@ -274,6 +308,8 @@ void __init x86_mrst_early_setup(void)
        x86_platform.calibrate_tsc = mrst_calibrate_tsc;
        x86_platform.i8042_detect = mrst_i8042_detect;
        x86_init.timers.wallclock_init = mrst_rtc_init;
+       x86_platform.get_nmi_reason = mrst_get_nmi_reason;
+
        x86_init.pci.init = pci_mrst_init;
        x86_init.pci.fixup_irqs = x86_init_noop;
 
@@ -608,6 +644,7 @@ static void *msic_ocd_platform_data(void *info)
 }
 
 static const struct devs_id __initconst device_ids[] = {
+       {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
        {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
        {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
        {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
index 9281da7d91bd193c221e1f7ba7fc422ff3880dcd..c0ac06da57ac39a4c6d6b687962f6b878005997c 100644 (file)
@@ -70,7 +70,7 @@ static struct mrst_device mrst_devs[] = {
 /* 24 */ { 0x4110, 0 },                        /* Lincroft */
 };
 
-/* n.b. We ignore PCI-id 0x815 in LSS9 b/c MeeGo has no driver for it */
+/* n.b. We ignore PCI-id 0x815 in LSS9 b/c Linux has no driver for it */
 static u16 mrst_lss9_pci_ids[] = {0x080a, 0x0814, 0};
 static u16 mrst_lss10_pci_ids[] = {0x0800, 0x0801, 0x0802, 0x0803,
                                        0x0804, 0x0805, 0x080f, 0};
index a8ac6f1eb66d56c0b3aac1e65591a4b2f707b3ed..225bd0f0f675395643c47859e61e0e5b6354ecb1 100644 (file)
@@ -76,8 +76,8 @@ unsigned long vrtc_get_time(void)
 
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       /* vRTC YEAR reg contains the offset to 1960 */
-       year += 1960;
+       /* vRTC YEAR reg contains the offset to 1972 */
+       year += 1972;
 
        printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
                "mon: %d year: %d\n", sec, min, hour, mday, mon, year);
index 118c143a9cb49ca03ced909f1a0744902889d701..2c32df6fe23167a6ca3955fdac07444f6f2fbc34 100644 (file)
@@ -11,7 +11,7 @@
 #endif
 
 #define KSTK_EIP(tsk) KSTK_REG(tsk, HOST_IP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_IP)
+#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_SP)
 #define KSTK_EBP(tsk) KSTK_REG(tsk, HOST_BP)
 
 #define ARCH_IS_STACKGROW(address) \
index da8afd576a6b7d161e3e81f2997912a73fec3d31..1f928659c338e6e5cfcf6386446f087f41f1e22f 100644 (file)
@@ -1356,7 +1356,7 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
        int cpu = (long)hcpu;
        switch (action) {
        case CPU_UP_PREPARE:
-               per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+               xen_vcpu_setup(cpu);
                if (xen_have_vector_callback)
                        xen_init_lock_cpu(cpu);
                break;
@@ -1386,7 +1386,6 @@ static void __init xen_hvm_guest_init(void)
        xen_hvm_smp_init();
        register_cpu_notifier(&xen_hvm_cpu_notifier);
        xen_unplug_emulated_devices();
-       have_vcpu_info_placement = 0;
        x86_init.irqs.intr_init = xen_init_IRQ;
        xen_hvm_init_time_ops();
        xen_hvm_init_mmu_ops();
index 6bbfd7ac5e814b10c96b925407c18cfaabb32453..5a40d24ba3316b85b42e5ef5d00280b89a2033b9 100644 (file)
@@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
 
        if (shared == NULL) {
                struct vm_struct *area =
-                       alloc_vm_area(PAGE_SIZE * max_nr_gframes);
+                       alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL);
                BUG_ON(area == NULL);
                shared = area->addr;
                *__shared = shared;
index f43c8a5840ae488131dbf395d5eaf96e2fea876d..ea70e6c80cd34f0c2b563ceabcc7189027fc5182 100644 (file)
@@ -1379,15 +1379,19 @@ get_rq:
                 */
                if (list_empty(&plug->list))
                        trace_block_plug(q);
-               else if (!plug->should_sort) {
-                       struct request *__rq;
+               else {
+                       if (!plug->should_sort) {
+                               struct request *__rq;
 
-                       __rq = list_entry_rq(plug->list.prev);
-                       if (__rq->q != q)
-                               plug->should_sort = 1;
+                               __rq = list_entry_rq(plug->list.prev);
+                               if (__rq->q != q)
+                                       plug->should_sort = 1;
+                       }
+                       if (request_count >= BLK_MAX_REQUEST_COUNT) {
+                               blk_flush_plug_list(plug, false);
+                               trace_block_plug(q);
+                       }
                }
-               if (request_count >= BLK_MAX_REQUEST_COUNT)
-                       blk_flush_plug_list(plug, false);
                list_add_tail(&req->queuelist, &plug->list);
                drive_stat_acct(req, 1);
        } else {
index e663ac2d8e68f70ff17ce274f3cebec16c1dd18c..164cd0059706214e53c01b780b353fca98d9b829 100644 (file)
@@ -204,10 +204,11 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
                if (!iov[i].iov_len)
                        return -EINVAL;
 
-               if (uaddr & queue_dma_alignment(q)) {
+               /*
+                * Keep going so we check length of all segments
+                */
+               if (uaddr & queue_dma_alignment(q))
                        unaligned = 1;
-                       break;
-               }
        }
 
        if (unaligned || (q->dma_pad_mask & len) || map_data)
index 9253839714ff95b4acc6da413bd87f610ddce44c..02e9fca808256f762e0af44e8a1055c322b51b40 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mutex.h>
 #include <linux/idr.h>
 #include <linux/log2.h>
-#include <linux/ctype.h>
 
 #include "blk.h"
 
@@ -916,74 +915,6 @@ static int __init genhd_device_init(void)
 
 subsys_initcall(genhd_device_init);
 
-static ssize_t alias_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
-{
-       struct gendisk *disk = dev_to_disk(dev);
-       ssize_t ret = 0;
-
-       if (disk->alias)
-               ret = snprintf(buf, ALIAS_LEN, "%s\n", disk->alias);
-       return ret;
-}
-
-static ssize_t alias_store(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
-{
-       struct gendisk *disk = dev_to_disk(dev);
-       char *alias;
-       char *envp[] = { NULL, NULL };
-       unsigned char c;
-       int i;
-       ssize_t ret = count;
-
-       if (!count)
-               return -EINVAL;
-
-       if (count >= ALIAS_LEN) {
-               printk(KERN_ERR "alias: alias is too long\n");
-               return -EINVAL;
-       }
-
-       /* Validation check */
-       for (i = 0; i < count; i++) {
-               c = buf[i];
-               if (i == count - 1 && c == '\n')
-                       break;
-               if (!isalnum(c) && c != '_' && c != '-') {
-                       printk(KERN_ERR "alias: invalid alias\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (disk->alias) {
-               printk(KERN_INFO "alias: %s is already assigned (%s)\n",
-                      disk->disk_name, disk->alias);
-               return -EINVAL;
-       }
-
-       alias = kasprintf(GFP_KERNEL, "%s", buf);
-       if (!alias)
-               return -ENOMEM;
-
-       if (alias[count - 1] == '\n')
-               alias[count - 1] = '\0';
-
-       envp[0] = kasprintf(GFP_KERNEL, "ALIAS=%s", alias);
-       if (!envp[0]) {
-               kfree(alias);
-               return -ENOMEM;
-       }
-
-       disk->alias = alias;
-       printk(KERN_INFO "alias: assigned %s to %s\n", alias, disk->disk_name);
-
-       kobject_uevent_env(&dev->kobj, KOBJ_ADD, envp);
-
-       kfree(envp[0]);
-       return ret;
-}
-
 static ssize_t disk_range_show(struct device *dev,
                               struct device_attribute *attr, char *buf)
 {
@@ -1043,7 +974,6 @@ static ssize_t disk_discard_alignment_show(struct device *dev,
        return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue));
 }
 
-static DEVICE_ATTR(alias, S_IRUGO|S_IWUSR, alias_show, alias_store);
 static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
 static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL);
 static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
@@ -1066,7 +996,6 @@ static struct device_attribute dev_attr_fail_timeout =
 #endif
 
 static struct attribute *disk_attrs[] = {
-       &dev_attr_alias.attr,
        &dev_attr_range.attr,
        &dev_attr_ext_range.attr,
        &dev_attr_removable.attr,
index a816f24f2d527993aea1fb724680857e77a06ff2..a0f768c1d9aa75fdb94a70dba711e175d8f66c9f 100644 (file)
@@ -383,6 +383,7 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_blkcipher rblkcipher;
@@ -404,6 +405,12 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
@@ -457,6 +464,7 @@ static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_blkcipher rblkcipher;
@@ -478,6 +486,12 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index 701556ffaaef0e6ca21256b52a8b594904852f9e..04add3dca6fe44dfc242e89a36741c56786327fa 100644 (file)
@@ -111,6 +111,7 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_aead raead;
@@ -132,6 +133,12 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
@@ -190,6 +197,7 @@ static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_aead raead;
@@ -210,6 +218,12 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 
 static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
index a3e6ef99394a9e78c7408ea4db65caa652004a1d..ac93c99cfae85abbc7fa433d94ef3fe80437cbb0 100644 (file)
@@ -399,6 +399,7 @@ static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
        return sizeof(struct crypto_shash *);
 }
 
+#ifdef CONFIG_NET
 static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_hash rhash;
@@ -416,6 +417,12 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index 2572d26001364b6206b300ecbc42ca18dfca9182..1e61d1a888b2b76f1b1e2fc8ac67e7741b221f45 100644 (file)
@@ -494,6 +494,7 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
                return crypto_init_blkcipher_ops_async(tfm);
 }
 
+#ifdef CONFIG_NET
 static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_blkcipher rblkcipher;
@@ -515,6 +516,12 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index 2abca780312d74246c60d7fcc9f6e9bf71f421c0..0605a2bbba75e17e67e59f602f1d12c453404031 100644 (file)
@@ -44,9 +44,6 @@ static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
 
        down_read(&crypto_alg_sem);
 
-       if (list_empty(&crypto_alg_list))
-               return NULL;
-
        list_for_each_entry(q, &crypto_alg_list, cra_list) {
                int match = 0;
 
index fefda78a6a2aa925d29e776dc87a956a605a2ab2..2e458e5482d0c5708cbab83dddaad11215c28a0e 100644 (file)
@@ -48,6 +48,7 @@ static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm)
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_comp rpcomp;
@@ -62,6 +63,12 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index feb7de00f437380fc8e95a3bf21398c9b4b1ce23..64f864fa8043740f50bc186e58a2ee37d8a1499a 100644 (file)
@@ -60,6 +60,7 @@ static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_rng rrng;
@@ -76,6 +77,12 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index ea8a9c6e21e371170606863ecb5f8cc7a5030ea8..9100912716ae948fa57da13b9030a248f0460942 100644 (file)
@@ -524,6 +524,7 @@ static unsigned int crypto_shash_extsize(struct crypto_alg *alg)
        return alg->cra_ctxsize;
 }
 
+#ifdef CONFIG_NET
 static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_hash rhash;
@@ -541,6 +542,12 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index 55accb7018bb24776f32541fddfe7cf7498383f8..cc70f3fdcdd1a0f1d4222f6f7e6a84ca9ff7ebf5 100644 (file)
@@ -269,16 +269,17 @@ acpi_status acpi_hw_clear_acpi_status(void)
 
        status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
                                        ACPI_BITMASK_ALL_FIXED_STATUS);
-       if (ACPI_FAILURE(status)) {
-               goto unlock_and_exit;
-       }
+
+       acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
+
+       if (ACPI_FAILURE(status))
+               goto exit;
 
        /* Clear the GPE Bits in all GPE registers in all GPE blocks */
 
        status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
 
-      unlock_and_exit:
-       acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
+exit:
        return_ACPI_STATUS(status);
 }
 
index 127408069ca7fa745953fd5a8e164cd74779c680..631b9477b99c02f827103aa00a8d3a83c380d359 100644 (file)
@@ -932,7 +932,8 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
 static int erst_open_pstore(struct pstore_info *psi);
 static int erst_close_pstore(struct pstore_info *psi);
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-                          struct timespec *time, struct pstore_info *psi);
+                          struct timespec *time, char **buf,
+                          struct pstore_info *psi);
 static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
                       size_t size, struct pstore_info *psi);
 static int erst_clearer(enum pstore_type_id type, u64 id,
@@ -986,17 +987,23 @@ static int erst_close_pstore(struct pstore_info *psi)
 }
 
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-                          struct timespec *time, struct pstore_info *psi)
+                          struct timespec *time, char **buf,
+                          struct pstore_info *psi)
 {
        int rc;
        ssize_t len = 0;
        u64 record_id;
-       struct cper_pstore_record *rcd = (struct cper_pstore_record *)
-                                       (erst_info.buf - sizeof(*rcd));
+       struct cper_pstore_record *rcd;
+       size_t rcd_len = sizeof(*rcd) + erst_info.bufsize;
 
        if (erst_disable)
                return -ENODEV;
 
+       rcd = kmalloc(rcd_len, GFP_KERNEL);
+       if (!rcd) {
+               rc = -ENOMEM;
+               goto out;
+       }
 skip:
        rc = erst_get_record_id_next(&reader_pos, &record_id);
        if (rc)
@@ -1004,22 +1011,27 @@ skip:
 
        /* no more record */
        if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-               rc = -1;
+               rc = -EINVAL;
                goto out;
        }
 
-       len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
-                       erst_info.bufsize);
+       len = erst_read(record_id, &rcd->hdr, rcd_len);
        /* The record may be cleared by others, try read next record */
        if (len == -ENOENT)
                goto skip;
-       else if (len < 0) {
-               rc = -1;
+       else if (len < sizeof(*rcd)) {
+               rc = -EIO;
                goto out;
        }
        if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
                goto skip;
 
+       *buf = kmalloc(len, GFP_KERNEL);
+       if (*buf == NULL) {
+               rc = -ENOMEM;
+               goto out;
+       }
+       memcpy(*buf, rcd->data, len - sizeof(*rcd));
        *id = record_id;
        if (uuid_le_cmp(rcd->sec_hdr.section_type,
                        CPER_SECTION_TYPE_DMESG) == 0)
@@ -1037,6 +1049,7 @@ skip:
        time->tv_nsec = 0;
 
 out:
+       kfree(rcd);
        return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
index 04ae1c88c03c519d404acfc761cca171c9067c9e..cfc0cc10af39f4e948d98a0d9de9d3e988a44fd1 100644 (file)
@@ -76,7 +76,7 @@ static void __iomem *__acpi_ioremap_fast(phys_addr_t paddr,
 {
        struct acpi_iomap *map;
 
-       map = __acpi_find_iomap(paddr, size);
+       map = __acpi_find_iomap(paddr, size/8);
        if (map)
                return map->vaddr + (paddr - map->paddr);
        else
index 437ddbf0c49abbd521dde72eae7011c5e4d3672f..9ecec98bc76e9aa030c3c5c0c060ba283e1dcf64 100644 (file)
@@ -911,10 +911,7 @@ void __init acpi_early_init(void)
        }
 #endif
 
-       status =
-           acpi_enable_subsystem(~
-                                 (ACPI_NO_HARDWARE_INIT |
-                                  ACPI_NO_ACPI_ENABLE));
+       status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE);
        if (ACPI_FAILURE(status)) {
                printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
                goto error0;
@@ -935,8 +932,7 @@ static int __init acpi_bus_init(void)
 
        acpi_os_initialize1();
 
-       status =
-           acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
+       status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
        if (ACPI_FAILURE(status)) {
                printk(KERN_ERR PREFIX
                       "Unable to start the ACPI Interpreter\n");
index a4e0f1ba6040c7f398f08f8816090ec5524ea629..9d7bc9f6b6cc662d52f7ba1802c0d2a7f524a7d1 100644 (file)
@@ -426,7 +426,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
 
        if (action == CPU_ONLINE && pr) {
                acpi_processor_ppc_has_changed(pr, 0);
-               acpi_processor_cst_has_changed(pr);
+               acpi_processor_hotplug(pr);
                acpi_processor_reevaluate_tstate(pr, action);
                acpi_processor_tstate_has_changed(pr);
        }
@@ -503,8 +503,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
        acpi_processor_get_throttling_info(pr);
        acpi_processor_get_limit_info(pr);
 
-
-       if (cpuidle_get_driver() == &acpi_idle_driver)
+       if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
                acpi_processor_power_init(pr, device);
 
        pr->cdev = thermal_cooling_device_register("Processor", device,
@@ -800,17 +799,9 @@ static int __init acpi_processor_init(void)
 
        memset(&errata, 0, sizeof(errata));
 
-       if (!cpuidle_register_driver(&acpi_idle_driver)) {
-               printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
-                       acpi_idle_driver.name);
-       } else {
-               printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n",
-                       cpuidle_get_driver()->name);
-       }
-
        result = acpi_bus_register_driver(&acpi_processor_driver);
        if (result < 0)
-               goto out_cpuidle;
+               return result;
 
        acpi_processor_install_hotplug_notify();
 
@@ -821,11 +812,6 @@ static int __init acpi_processor_init(void)
        acpi_processor_throttling_init();
 
        return 0;
-
-out_cpuidle:
-       cpuidle_unregister_driver(&acpi_idle_driver);
-
-       return result;
 }
 
 static void __exit acpi_processor_exit(void)
index 9b88f9828d8ca2ce98dc69be2606ffcc069d323e..0e8e2de2ed3e3a6b18ab07d07713a529295f31aa 100644 (file)
@@ -224,7 +224,6 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 /*
  * Suspend / resume control
  */
-static int acpi_idle_suspend;
 static u32 saved_bm_rld;
 
 static void acpi_idle_bm_rld_save(void)
@@ -243,21 +242,13 @@ static void acpi_idle_bm_rld_restore(void)
 
 int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
 {
-       if (acpi_idle_suspend == 1)
-               return 0;
-
        acpi_idle_bm_rld_save();
-       acpi_idle_suspend = 1;
        return 0;
 }
 
 int acpi_processor_resume(struct acpi_device * device)
 {
-       if (acpi_idle_suspend == 0)
-               return 0;
-
        acpi_idle_bm_rld_restore();
-       acpi_idle_suspend = 0;
        return 0;
 }
 
@@ -741,66 +732,65 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
 /**
  * acpi_idle_enter_c1 - enters an ACPI C1 state-type
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver containing cpuidle state info
+ * @index: index of target state
  *
  * This is equivalent to the HALT instruction.
  */
 static int acpi_idle_enter_c1(struct cpuidle_device *dev,
-                             struct cpuidle_state *state)
+               struct cpuidle_driver *drv, int index)
 {
        ktime_t  kt1, kt2;
        s64 idle_time;
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+       struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+       struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 
        pr = __this_cpu_read(processors);
+       dev->last_residency = 0;
 
        if (unlikely(!pr))
-               return 0;
+               return -EINVAL;
 
        local_irq_disable();
 
-       /* Do not access any ACPI IO ports in suspend path */
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return 0;
-       }
-
        lapic_timer_state_broadcast(pr, cx, 1);
        kt1 = ktime_get_real();
        acpi_idle_do_entry(cx);
        kt2 = ktime_get_real();
        idle_time =  ktime_to_us(ktime_sub(kt2, kt1));
 
+       /* Update device last_residency*/
+       dev->last_residency = (int)idle_time;
+
        local_irq_enable();
        cx->usage++;
        lapic_timer_state_broadcast(pr, cx, 0);
 
-       return idle_time;
+       return index;
 }
 
 /**
  * acpi_idle_enter_simple - enters an ACPI state without BM handling
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver with cpuidle state information
+ * @index: the index of suggested state
  */
 static int acpi_idle_enter_simple(struct cpuidle_device *dev,
-                                 struct cpuidle_state *state)
+               struct cpuidle_driver *drv, int index)
 {
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+       struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+       struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
        ktime_t  kt1, kt2;
        s64 idle_time_ns;
        s64 idle_time;
 
        pr = __this_cpu_read(processors);
+       dev->last_residency = 0;
 
        if (unlikely(!pr))
-               return 0;
-
-       if (acpi_idle_suspend)
-               return(acpi_idle_enter_c1(dev, state));
+               return -EINVAL;
 
        local_irq_disable();
 
@@ -815,7 +805,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
                if (unlikely(need_resched())) {
                        current_thread_info()->status |= TS_POLLING;
                        local_irq_enable();
-                       return 0;
+                       return -EINVAL;
                }
        }
 
@@ -837,6 +827,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        idle_time = idle_time_ns;
        do_div(idle_time, NSEC_PER_USEC);
 
+       /* Update device last_residency*/
+       dev->last_residency = (int)idle_time;
+
        /* Tell the scheduler how much we idled: */
        sched_clock_idle_wakeup_event(idle_time_ns);
 
@@ -848,7 +841,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 
        lapic_timer_state_broadcast(pr, cx, 0);
        cx->time += idle_time;
-       return idle_time;
+       return index;
 }
 
 static int c3_cpu_count;
@@ -857,37 +850,37 @@ static DEFINE_RAW_SPINLOCK(c3_lock);
 /**
  * acpi_idle_enter_bm - enters C3 with proper BM handling
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver containing state data
+ * @index: the index of suggested state
  *
  * If BM is detected, the deepest non-C3 idle state is entered instead.
  */
 static int acpi_idle_enter_bm(struct cpuidle_device *dev,
-                             struct cpuidle_state *state)
+               struct cpuidle_driver *drv, int index)
 {
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+       struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+       struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
        ktime_t  kt1, kt2;
        s64 idle_time_ns;
        s64 idle_time;
 
 
        pr = __this_cpu_read(processors);
+       dev->last_residency = 0;
 
        if (unlikely(!pr))
-               return 0;
-
-       if (acpi_idle_suspend)
-               return(acpi_idle_enter_c1(dev, state));
+               return -EINVAL;
 
        if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
-               if (dev->safe_state) {
-                       dev->last_state = dev->safe_state;
-                       return dev->safe_state->enter(dev, dev->safe_state);
+               if (drv->safe_state_index >= 0) {
+                       return drv->states[drv->safe_state_index].enter(dev,
+                                               drv, drv->safe_state_index);
                } else {
                        local_irq_disable();
                        acpi_safe_halt();
                        local_irq_enable();
-                       return 0;
+                       return -EINVAL;
                }
        }
 
@@ -904,7 +897,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                if (unlikely(need_resched())) {
                        current_thread_info()->status |= TS_POLLING;
                        local_irq_enable();
-                       return 0;
+                       return -EINVAL;
                }
        }
 
@@ -954,6 +947,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
        idle_time = idle_time_ns;
        do_div(idle_time, NSEC_PER_USEC);
 
+       /* Update device last_residency*/
+       dev->last_residency = (int)idle_time;
+
        /* Tell the scheduler how much we idled: */
        sched_clock_idle_wakeup_event(idle_time_ns);
 
@@ -965,7 +961,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 
        lapic_timer_state_broadcast(pr, cx, 0);
        cx->time += idle_time;
-       return idle_time;
+       return index;
 }
 
 struct cpuidle_driver acpi_idle_driver = {
@@ -974,14 +970,16 @@ struct cpuidle_driver acpi_idle_driver = {
 };
 
 /**
- * acpi_processor_setup_cpuidle - prepares and configures CPUIDLE
+ * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE
+ * device i.e. per-cpu data
+ *
  * @pr: the ACPI processor
  */
-static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr)
 {
        int i, count = CPUIDLE_DRIVER_STATE_START;
        struct acpi_processor_cx *cx;
-       struct cpuidle_state *state;
+       struct cpuidle_state_usage *state_usage;
        struct cpuidle_device *dev = &pr->power.dev;
 
        if (!pr->flags.power_setup_done)
@@ -992,9 +990,62 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
        }
 
        dev->cpu = pr->id;
+
+       if (max_cstate == 0)
+               max_cstate = 1;
+
+       for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
+               cx = &pr->power.states[i];
+               state_usage = &dev->states_usage[count];
+
+               if (!cx->valid)
+                       continue;
+
+#ifdef CONFIG_HOTPLUG_CPU
+               if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+                   !pr->flags.has_cst &&
+                   !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+                       continue;
+#endif
+
+               cpuidle_set_statedata(state_usage, cx);
+
+               count++;
+               if (count == CPUIDLE_STATE_MAX)
+                       break;
+       }
+
+       dev->state_count = count;
+
+       if (!count)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ * acpi_processor_setup_cpuidle states- prepares and configures cpuidle
+ * global state data i.e. idle routines
+ *
+ * @pr: the ACPI processor
+ */
+static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
+{
+       int i, count = CPUIDLE_DRIVER_STATE_START;
+       struct acpi_processor_cx *cx;
+       struct cpuidle_state *state;
+       struct cpuidle_driver *drv = &acpi_idle_driver;
+
+       if (!pr->flags.power_setup_done)
+               return -EINVAL;
+
+       if (pr->flags.power == 0)
+               return -EINVAL;
+
+       drv->safe_state_index = -1;
        for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-               dev->states[i].name[0] = '\0';
-               dev->states[i].desc[0] = '\0';
+               drv->states[i].name[0] = '\0';
+               drv->states[i].desc[0] = '\0';
        }
 
        if (max_cstate == 0)
@@ -1002,7 +1053,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
 
        for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
                cx = &pr->power.states[i];
-               state = &dev->states[count];
 
                if (!cx->valid)
                        continue;
@@ -1013,8 +1063,8 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
                    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
                        continue;
 #endif
-               cpuidle_set_statedata(state, cx);
 
+               state = &drv->states[count];
                snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
                strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
                state->exit_latency = cx->latency;
@@ -1027,13 +1077,13 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
                                state->flags |= CPUIDLE_FLAG_TIME_VALID;
 
                        state->enter = acpi_idle_enter_c1;
-                       dev->safe_state = state;
+                       drv->safe_state_index = count;
                        break;
 
                        case ACPI_STATE_C2:
                        state->flags |= CPUIDLE_FLAG_TIME_VALID;
                        state->enter = acpi_idle_enter_simple;
-                       dev->safe_state = state;
+                       drv->safe_state_index = count;
                        break;
 
                        case ACPI_STATE_C3:
@@ -1049,7 +1099,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
                        break;
        }
 
-       dev->state_count = count;
+       drv->state_count = count;
 
        if (!count)
                return -EINVAL;
@@ -1057,7 +1107,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
        return 0;
 }
 
-int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+int acpi_processor_hotplug(struct acpi_processor *pr)
 {
        int ret = 0;
 
@@ -1078,7 +1128,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
        cpuidle_disable_device(&pr->power.dev);
        acpi_processor_get_power_info(pr);
        if (pr->flags.power) {
-               acpi_processor_setup_cpuidle(pr);
+               acpi_processor_setup_cpuidle_cx(pr);
                ret = cpuidle_enable_device(&pr->power.dev);
        }
        cpuidle_resume_and_unlock();
@@ -1086,10 +1136,72 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
        return ret;
 }
 
+int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+{
+       int cpu;
+       struct acpi_processor *_pr;
+
+       if (disabled_by_idle_boot_param())
+               return 0;
+
+       if (!pr)
+               return -EINVAL;
+
+       if (nocst)
+               return -ENODEV;
+
+       if (!pr->flags.power_setup_done)
+               return -ENODEV;
+
+       /*
+        * FIXME:  Design the ACPI notification to make it once per
+        * system instead of once per-cpu.  This condition is a hack
+        * to make the code that updates C-States be called once.
+        */
+
+       if (smp_processor_id() == 0 &&
+                       cpuidle_get_driver() == &acpi_idle_driver) {
+
+               cpuidle_pause_and_lock();
+               /* Protect against cpu-hotplug */
+               get_online_cpus();
+
+               /* Disable all cpuidle devices */
+               for_each_online_cpu(cpu) {
+                       _pr = per_cpu(processors, cpu);
+                       if (!_pr || !_pr->flags.power_setup_done)
+                               continue;
+                       cpuidle_disable_device(&_pr->power.dev);
+               }
+
+               /* Populate Updated C-state information */
+               acpi_processor_setup_cpuidle_states(pr);
+
+               /* Enable all cpuidle devices */
+               for_each_online_cpu(cpu) {
+                       _pr = per_cpu(processors, cpu);
+                       if (!_pr || !_pr->flags.power_setup_done)
+                               continue;
+                       acpi_processor_get_power_info(_pr);
+                       if (_pr->flags.power) {
+                               acpi_processor_setup_cpuidle_cx(_pr);
+                               cpuidle_enable_device(&_pr->power.dev);
+                       }
+               }
+               put_online_cpus();
+               cpuidle_resume_and_unlock();
+       }
+
+       return 0;
+}
+
+static int acpi_processor_registered;
+
 int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
                              struct acpi_device *device)
 {
        acpi_status status = 0;
+       int retval;
        static int first_run;
 
        if (disabled_by_idle_boot_param())
@@ -1126,9 +1238,26 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
         * platforms that only support C1.
         */
        if (pr->flags.power) {
-               acpi_processor_setup_cpuidle(pr);
-               if (cpuidle_register_device(&pr->power.dev))
-                       return -EIO;
+               /* Register acpi_idle_driver if not already registered */
+               if (!acpi_processor_registered) {
+                       acpi_processor_setup_cpuidle_states(pr);
+                       retval = cpuidle_register_driver(&acpi_idle_driver);
+                       if (retval)
+                               return retval;
+                       printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
+                                       acpi_idle_driver.name);
+               }
+               /* Register per-cpu cpuidle_device. Cpuidle driver
+                * must already be registered before registering device
+                */
+               acpi_processor_setup_cpuidle_cx(pr);
+               retval = cpuidle_register_device(&pr->power.dev);
+               if (retval) {
+                       if (acpi_processor_registered == 0)
+                               cpuidle_unregister_driver(&acpi_idle_driver);
+                       return retval;
+               }
+               acpi_processor_registered++;
        }
        return 0;
 }
@@ -1139,8 +1268,13 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
        if (disabled_by_idle_boot_param())
                return 0;
 
-       cpuidle_unregister_device(&pr->power.dev);
-       pr->flags.power_setup_done = 0;
+       if (pr->flags.power) {
+               cpuidle_unregister_device(&pr->power.dev);
+               acpi_processor_registered--;
+               if (acpi_processor_registered == 0)
+                       cpuidle_unregister_driver(&acpi_idle_driver);
+       }
 
+       pr->flags.power_setup_done = 0;
        return 0;
 }
index 449c556274c052cf4c9fd221c577b7735bcdca0f..8ab80bafe3f1604f3e05e7287ed5fe4f9ed1e6fb 100644 (file)
@@ -1062,13 +1062,12 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
        if (!id)
                return;
 
-       id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
+       id->id = kstrdup(dev_id, GFP_KERNEL);
        if (!id->id) {
                kfree(id);
                return;
        }
 
-       strcpy(id->id, dev_id);
        list_add_tail(&id->list, &device->pnp.ids);
 }
 
index c538d0ef10ff648de4140eb54f6f7c8c3c7bc88f..9f66181c814e78e2fc40c88ba743b5aa062e50e9 100644 (file)
@@ -706,11 +706,23 @@ static void __exit interrupt_stats_exit(void)
        return;
 }
 
+static ssize_t
+acpi_show_profile(struct device *dev, struct device_attribute *attr,
+                 char *buf)
+{
+       return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
+}
+
+static const struct device_attribute pm_profile_attr =
+       __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
+
 int __init acpi_sysfs_init(void)
 {
        int result;
 
        result = acpi_tables_sysfs_init();
-
+       if (result)
+               return result;
+       result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
        return result;
 }
index fb7b90b059226c7235c9c5a719fda26aeb6ba981..cf26222a93c5ddc7a88092ab9c7fcdf262a45ae1 100644 (file)
@@ -390,6 +390,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        /* Promise */
        { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },   /* PDC42819 */
 
+       /* Asmedia */
+       { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1061 */
+
        /* Generic, PCI class code for AHCI */
        { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
index 004f2ce3dc737a01ddc9adab97958e1cd88d4b7c..43b875810d1b7b91c98386fb6f3a5c58be79fdb9 100644 (file)
@@ -65,9 +65,9 @@ static struct scsi_host_template ahci_platform_sht = {
 static int __init ahci_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct ahci_platform_data *pdata = dev->platform_data;
+       struct ahci_platform_data *pdata = dev_get_platdata(dev);
        const struct platform_device_id *id = platform_get_device_id(pdev);
-       struct ata_port_info pi = ahci_port_info[id->driver_data];
+       struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
        const struct ata_port_info *ppi[] = { &pi, NULL };
        struct ahci_host_priv *hpriv;
        struct ata_host *host;
@@ -191,7 +191,7 @@ err0:
 static int __devexit ahci_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct ahci_platform_data *pdata = dev->platform_data;
+       struct ahci_platform_data *pdata = dev_get_platdata(dev);
        struct ata_host *host = dev_get_drvdata(dev);
 
        ata_host_detach(host);
index f22957c2769a749f66c28c1f310acfd8a0446b92..a9b282038000c921eca51f7484866d890dec5d54 100644 (file)
@@ -2883,7 +2883,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
            sata_scr_read(link, SCR_STATUS, &sstatus))
                rc = -ERESTART;
 
-       if (rc == -ERESTART || try >= max_tries) {
+       if (try >= max_tries) {
                /*
                 * Thaw host port even if reset failed, so that the port
                 * can be retried on the next phy event.  This risks
@@ -2909,6 +2909,16 @@ int ata_eh_reset(struct ata_link *link, int classify,
                ata_eh_acquire(ap);
        }
 
+       /*
+        * While disks spinup behind PMP, some controllers fail sending SRST.
+        * They need to be reset - as well as the PMP - before retrying.
+        */
+       if (rc == -ERESTART) {
+               if (ata_is_host_link(link))
+                       ata_eh_thaw_port(ap);
+               goto out;
+       }
+
        if (try == max_tries - 1) {
                sata_down_spd_limit(link, 0);
                if (slave)
index 104462dbc524aa56acf56da7b3b19e885ba3229f..21b80c555c607768912953c1f355bf25615c8a22 100644 (file)
@@ -389,12 +389,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
                        /* link reports offline after LPM */
                        link->flags |= ATA_LFLAG_NO_LPM;
 
-                       /* Class code report is unreliable and SRST
-                        * times out under certain configurations.
-                        */
+                       /* Class code report is unreliable. */
                        if (link->pmp < 5)
-                               link->flags |= ATA_LFLAG_NO_SRST |
-                                              ATA_LFLAG_ASSUME_ATA;
+                               link->flags |= ATA_LFLAG_ASSUME_ATA;
 
                        /* port 5 is for SEMB device and it doesn't like SRST */
                        if (link->pmp == 5)
index 72a9770ac42f51e95db81f318d6aa30acdc690d2..2a5412e7e9c11c85d23c12959ad503f9f2e182aa 100644 (file)
@@ -1217,6 +1217,10 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
 
 /**
  *     __ata_change_queue_depth - helper for ata_scsi_change_queue_depth
+ *     @ap: ATA port to which the device change the queue depth
+ *     @sdev: SCSI device to configure queue depth for
+ *     @queue_depth: new queue depth
+ *     @reason: calling context
  *
  *     libsas and libata have different approaches for associating a sdev to
  *     its ata_port.
index 63d53277d6a92f4393cd22563d75c4b9b8d32462..4cadfa28f940450ee2f5a890af44e34ad583e921 100644 (file)
@@ -2533,10 +2533,12 @@ static int ata_pci_init_one(struct pci_dev *pdev,
        if (rc)
                goto out;
 
+#ifdef CONFIG_ATA_BMDMA
        if (bmdma)
                /* prepare and activate BMDMA host */
                rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
        else
+#endif
                /* prepare and activate SFF host */
                rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
        if (rc)
@@ -2544,10 +2546,12 @@ static int ata_pci_init_one(struct pci_dev *pdev,
        host->private_data = host_priv;
        host->flags |= hflags;
 
+#ifdef CONFIG_ATA_BMDMA
        if (bmdma) {
                pci_set_master(pdev);
                rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
        } else
+#endif
                rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
 out:
        if (rc == 0)
index a72ab0dde4e52332104003fd63806d85f271c037..2a472c5bb7db7015d76118434a8d50e7795a07d1 100644 (file)
@@ -52,7 +52,7 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
        }
 
        ret = of_irq_to_resource(dn, 0, &irq_res);
-       if (ret == NO_IRQ)
+       if (!ret)
                irq_res.start = irq_res.end = 0;
        else
                irq_res.flags = 0;
index 447d9c05fb5a927a3d5b2c513fe4b8a70c36f625..95ec435f0eb425049a9a447a49aaea430df6f949 100644 (file)
@@ -104,7 +104,7 @@ static const struct ata_port_info sis_port_info = {
 };
 
 MODULE_AUTHOR("Uwe Koziolek");
-MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
+MODULE_DESCRIPTION("low-level driver for Silicon Integrated Systems SATA controller");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
index 82c865452c7080d180ec6a453ab1efb3e988dac3..d8b3d89db043e7e9ead44cb8b4a00946f4980fa6 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/kallsyms.h>
 #include <linux/mutex.h>
 #include <linux/async.h>
+#include <linux/pm_runtime.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -1742,6 +1743,8 @@ void device_shutdown(void)
                 */
                list_del_init(&dev->kobj.entry);
                spin_unlock(&devices_kset->list_lock);
+               /* Disable all device's runtime power management */
+               pm_runtime_disable(dev);
 
                if (dev->bus && dev->bus->shutdown) {
                        dev_dbg(dev, "shutdown\n");
index 793f796c4da3e1cd20143e1266d41246f2289b73..5693ecee9a4052a339b9eca105ff3704fffe29b4 100644 (file)
@@ -127,12 +127,13 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
                       nid, K(node_page_state(nid, NR_WRITEBACK)),
                       nid, K(node_page_state(nid, NR_FILE_PAGES)),
                       nid, K(node_page_state(nid, NR_FILE_MAPPED)),
-                      nid, K(node_page_state(nid, NR_ANON_PAGES)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+                      nid, K(node_page_state(nid, NR_ANON_PAGES)
                        + node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-                       HPAGE_PMD_NR
+                       HPAGE_PMD_NR),
+#else
+                      nid, K(node_page_state(nid, NR_ANON_PAGES)),
 #endif
-                      ),
                       nid, K(node_page_state(nid, NR_SHMEM)),
                       nid, node_page_state(nid, NR_KERNEL_STACK) *
                                THREAD_SIZE / 1024,
@@ -143,13 +144,14 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
                       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +
                                node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
                       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
-                      nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+                      nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
                        , nid,
                        K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-                       HPAGE_PMD_NR)
+                       HPAGE_PMD_NR));
+#else
+                      nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));
 #endif
-                      );
        n += hugetlb_report_node_meminfo(nid, buf + n);
        return n;
 }
index 5f0f85d5c5765558a25fa7ec165be968e5fbcabf..428e55e012dcd06f91ade3154c941aab6f1d5bb5 100644 (file)
@@ -229,7 +229,8 @@ int pm_clk_suspend(struct device *dev)
 
        list_for_each_entry_reverse(ce, &psd->clock_list, node) {
                if (ce->status < PCE_STATUS_ERROR) {
-                       clk_disable(ce->clk);
+                       if (ce->status == PCE_STATUS_ENABLED)
+                               clk_disable(ce->clk);
                        ce->status = PCE_STATUS_ACQUIRED;
                }
        }
index 7fa098464dae62921a5acf32af3537f649b604fe..c3d2dfcf438dd1735fcf401be9f8185440e9a1a9 100644 (file)
@@ -920,7 +920,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
  End:
        if (!error) {
                dev->power.is_suspended = true;
-               if (dev->power.wakeup_path && dev->parent)
+               if (dev->power.wakeup_path
+                   && dev->parent && !dev->parent->power.ignore_children)
                        dev->parent->power.wakeup_path = true;
        }
 
index 434a6c01167521007e14f11ad0d7f2accdb8cf7b..95706fa24c73559ecd04aacf8c0a6296616c452f 100644 (file)
@@ -669,7 +669,7 @@ struct srcu_notifier_head *opp_get_notifier(struct device *dev)
        struct device_opp *dev_opp = find_device_opp(dev);
 
        if (IS_ERR(dev_opp))
-               return ERR_PTR(PTR_ERR(dev_opp)); /* matching type */
+               return ERR_CAST(dev_opp); /* matching type */
 
        return &dev_opp->head;
 }
index 30a94eadc200c7f89f7e2448126ad93cd6a6a2f2..86de6c50fc4181f796c5d0e3d20e796380f112b0 100644 (file)
@@ -212,11 +212,9 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
        if (!dev || !req) /*guard against callers passing in null */
                return -EINVAL;
 
-       if (dev_pm_qos_request_active(req)) {
-               WARN(1, KERN_ERR "dev_pm_qos_add_request() called for already "
-                       "added request\n");
+       if (WARN(dev_pm_qos_request_active(req),
+                "%s() called for already added request\n", __func__))
                return -EINVAL;
-       }
 
        req->dev = dev;
 
@@ -271,11 +269,9 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
        if (!req) /*guard against callers passing in null */
                return -EINVAL;
 
-       if (!dev_pm_qos_request_active(req)) {
-               WARN(1, KERN_ERR "dev_pm_qos_update_request() called for "
-                       "unknown object\n");
+       if (WARN(!dev_pm_qos_request_active(req),
+                "%s() called for unknown object\n", __func__))
                return -EINVAL;
-       }
 
        mutex_lock(&dev_pm_qos_mtx);
 
@@ -312,11 +308,9 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
        if (!req) /*guard against callers passing in null */
                return -EINVAL;
 
-       if (!dev_pm_qos_request_active(req)) {
-               WARN(1, KERN_ERR "dev_pm_qos_remove_request() called for "
-                       "unknown object\n");
+       if (WARN(!dev_pm_qos_request_active(req),
+                "%s() called for unknown object\n", __func__))
                return -EINVAL;
-       }
 
        mutex_lock(&dev_pm_qos_mtx);
 
index 486f94ef24d499bfe0d17eb379fe5043a94f36a5..8004ac30a7a8634bc7f963be8db2c6c1eac61ce4 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -4319,6 +4320,10 @@ static int __devinit cciss_pci_init(ctlr_info_t *h)
                dev_warn(&h->pdev->dev, "controller appears to be disabled\n");
                return -ENODEV;
        }
+
+       pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
+                               PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
+
        err = pci_enable_device(h->pdev);
        if (err) {
                dev_warn(&h->pdev->dev, "Unable to Enable PCI device\n");
@@ -5158,6 +5163,7 @@ reinit_after_soft_reset:
        h->cciss_max_sectors = 8192;
 
        rebuild_lun_table(h, 1, 0);
+       cciss_engage_scsi(h);
        h->busy_initializing = 0;
        return 1;
 
index 951a4e33b92b788b208d6320636b77422bf9474f..e820b68d2f6cd4d74382b85b5e020069294f00f3 100644 (file)
@@ -1720,5 +1720,6 @@ static int  cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
 /* If no tape support, then these become defined out of existence */
 
 #define cciss_scsi_setup(cntl_num)
+#define cciss_engage_scsi(h)
 
 #endif /* CONFIG_CISS_SCSI_TAPE */
index 3d806820280e3bc4aaa5e81d6bea411f6597e400..68b205a9338f631adbd98df74836b98aa95d27ac 100644 (file)
@@ -161,17 +161,19 @@ static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
        &xor_funcs
 };
 
-static loff_t get_loop_size(struct loop_device *lo, struct file *file)
+static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
 {
-       loff_t size, offset, loopsize;
+       loff_t size, loopsize;
 
        /* Compute loopsize in bytes */
        size = i_size_read(file->f_mapping->host);
-       offset = lo->lo_offset;
        loopsize = size - offset;
-       if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
-               loopsize = lo->lo_sizelimit;
+       /* offset is beyond i_size, wierd but possible */
+       if (loopsize < 0)
+               return 0;
 
+       if (sizelimit > 0 && sizelimit < loopsize)
+               loopsize = sizelimit;
        /*
         * Unfortunately, if we want to do I/O on the device,
         * the number of 512-byte sectors has to fit into a sector_t.
@@ -179,17 +181,25 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file)
        return loopsize >> 9;
 }
 
+static loff_t get_loop_size(struct loop_device *lo, struct file *file)
+{
+       return get_size(lo->lo_offset, lo->lo_sizelimit, file);
+}
+
 static int
-figure_loop_size(struct loop_device *lo)
+figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
 {
-       loff_t size = get_loop_size(lo, lo->lo_backing_file);
+       loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
        sector_t x = (sector_t)size;
 
        if (unlikely((loff_t)x != size))
                return -EFBIG;
-
+       if (lo->lo_offset != offset)
+               lo->lo_offset = offset;
+       if (lo->lo_sizelimit != sizelimit)
+               lo->lo_sizelimit = sizelimit;
        set_capacity(lo->lo_disk, x);
-       return 0;                                       
+       return 0;
 }
 
 static inline int
@@ -372,7 +382,8 @@ do_lo_receive(struct loop_device *lo,
 
        if (retval < 0)
                return retval;
-
+       if (retval != bvec->bv_len)
+               return -EIO;
        return 0;
 }
 
@@ -1058,9 +1069,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 
        if (lo->lo_offset != info->lo_offset ||
            lo->lo_sizelimit != info->lo_sizelimit) {
-               lo->lo_offset = info->lo_offset;
-               lo->lo_sizelimit = info->lo_sizelimit;
-               if (figure_loop_size(lo))
+               if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit))
                        return -EFBIG;
        }
        loop_config_discard(lo);
@@ -1246,7 +1255,7 @@ static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev)
        err = -ENXIO;
        if (unlikely(lo->lo_state != Lo_bound))
                goto out;
-       err = figure_loop_size(lo);
+       err = figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit);
        if (unlikely(err))
                goto out;
        sec = get_capacity(lo->lo_disk);
@@ -1284,13 +1293,19 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
                        goto out_unlocked;
                break;
        case LOOP_SET_STATUS:
-               err = loop_set_status_old(lo, (struct loop_info __user *) arg);
+               err = -EPERM;
+               if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+                       err = loop_set_status_old(lo,
+                                       (struct loop_info __user *)arg);
                break;
        case LOOP_GET_STATUS:
                err = loop_get_status_old(lo, (struct loop_info __user *) arg);
                break;
        case LOOP_SET_STATUS64:
-               err = loop_set_status64(lo, (struct loop_info64 __user *) arg);
+               err = -EPERM;
+               if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+                       err = loop_set_status64(lo,
+                                       (struct loop_info64 __user *) arg);
                break;
        case LOOP_GET_STATUS64:
                err = loop_get_status64(lo, (struct loop_info64 __user *) arg);
index 6b9a2000d56affdd7788ff26581ae587f3937f96..a79fb4f7ff622632809c2b93f47df93fb7561ccb 100644 (file)
@@ -630,6 +630,7 @@ static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t
                if (dev->status & 0x10)
                        return -ETIME;
 
+       memset(&hdr, 0, sizeof(hdr));
        hdr.magic = PG_MAGIC;
        hdr.dlen = dev->dlen;
        copy = 0;
index db7cb8111fbe58a89f21ee6ccea50467356bd38a..106beb194f3c8d438e105dab8d12aaecb8716103 100644 (file)
@@ -105,7 +105,7 @@ static int ath3k_load_firmware(struct usb_device *udev,
 
        pipe = usb_sndctrlpipe(udev, 0);
 
-       send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+       send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);
        if (!send_buf) {
                BT_ERR("Can't allocate memory chunk for firmware");
                return -ENOMEM;
@@ -176,7 +176,7 @@ static int ath3k_load_fwfile(struct usb_device *udev,
 
        count = firmware->size;
 
-       send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+       send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);
        if (!send_buf) {
                BT_ERR("Can't allocate memory chunk for firmware");
                return -ENOMEM;
index 8b1b643a519b330a8119ad5bde789ec105edfdfc..54952ab800b88b5e5ae34229f7602c71c11e45e1 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/module.h>
 
+#include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -65,6 +66,7 @@ struct bcm203x_data {
        unsigned long           state;
 
        struct work_struct      work;
+       atomic_t                shutdown;
 
        struct urb              *urb;
        unsigned char           *buffer;
@@ -97,6 +99,7 @@ static void bcm203x_complete(struct urb *urb)
 
                data->state = BCM203X_SELECT_MEMORY;
 
+               /* use workqueue to have a small delay */
                schedule_work(&data->work);
                break;
 
@@ -155,7 +158,10 @@ static void bcm203x_work(struct work_struct *work)
        struct bcm203x_data *data =
                container_of(work, struct bcm203x_data, work);
 
-       if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
+       if (atomic_read(&data->shutdown))
+               return;
+
+       if (usb_submit_urb(data->urb, GFP_KERNEL) < 0)
                BT_ERR("Can't submit URB");
 }
 
@@ -243,6 +249,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
 
        usb_set_intfdata(intf, data);
 
+       /* use workqueue to have a small delay */
        schedule_work(&data->work);
 
        return 0;
@@ -254,6 +261,9 @@ static void bcm203x_disconnect(struct usb_interface *intf)
 
        BT_DBG("intf %p", intf);
 
+       atomic_inc(&data->shutdown);
+       cancel_work_sync(&data->work);
+
        usb_kill_urb(data->urb);
 
        usb_set_intfdata(intf, NULL);
index 005919ab043c16bb4e699b4f58ee5a4fdbd94c6e..61b591470a90827280005b50b000907a7e7c2ac2 100644 (file)
@@ -568,22 +568,23 @@ static int bfusb_load_firmware(struct bfusb_data *data,
 
        BT_INFO("BlueFRITZ! USB loading firmware");
 
+       buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL);
+       if (!buf) {
+               BT_ERR("Can't allocate memory chunk for firmware");
+               return -ENOMEM;
+       }
+
        pipe = usb_sndctrlpipe(data->udev, 0);
 
        if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
                                0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
                BT_ERR("Can't change to loading configuration");
+               kfree(buf);
                return -EBUSY;
        }
 
        data->udev->toggle[0] = data->udev->toggle[1] = 0;
 
-       buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC);
-       if (!buf) {
-               BT_ERR("Can't allocate memory chunk for firmware");
-               return -ENOMEM;
-       }
-
        pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
 
        while (count) {
index f9b726091ad0bba89464bad3a59f363318eba508..fe4ebc375b3dafd274da41c803cbb9ac37754146 100644 (file)
@@ -100,6 +100,9 @@ static struct usb_device_id btusb_table[] = {
        /* Canyon CN-BTU1 with HID interfaces */
        { USB_DEVICE(0x0c10, 0x0000) },
 
+       /* Broadcom BCM20702A0 */
+       { USB_DEVICE(0x413c, 0x8197) },
+
        { }     /* Terminating entry */
 };
 
index 66cd0b8096ca426f9755f958797fb80560770f49..c92424ca1a55370dcdaa7798cb6eb1ae6fbdd90c 100644 (file)
@@ -1186,10 +1186,11 @@ static void gen6_cleanup(void)
 /* Certain Gen5 chipsets require require idling the GPU before
  * unmapping anything from the GTT when VT-d is enabled.
  */
-extern int intel_iommu_gfx_mapped;
 static inline int needs_idle_maps(void)
 {
+#ifdef CONFIG_INTEL_IOMMU
        const unsigned short gpu_devid = intel_private.pcidev->device;
+       extern int intel_iommu_gfx_mapped;
 
        /* Query intel_iommu to see if we need the workaround. Presumably that
         * was loaded first.
@@ -1198,7 +1199,7 @@ static inline int needs_idle_maps(void)
             gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
             intel_iommu_gfx_mapped)
                return 1;
-
+#endif
        return 0;
 }
 
@@ -1236,7 +1237,7 @@ static int i9xx_setup(void)
                intel_private.gtt_bus_addr = reg_addr + gtt_offset;
        }
 
-       if (needs_idle_maps());
+       if (needs_idle_maps())
                intel_private.base.do_idle_maps = 1;
 
        intel_i9xx_setup_flush();
index 63e19ba56bbea5a12ee784f023bd13a758eaf611..6035ab8d5ef7e25e6eae89fbfdc53476f248de8b 100644 (file)
@@ -941,7 +941,7 @@ void get_random_bytes(void *buf, int nbytes)
                if (!arch_get_random_long(&v))
                        break;
                
-               memcpy(buf, &v, chunk);
+               memcpy(p, &v, chunk);
                p += chunk;
                nbytes -= chunk;
        }
index edaa987621ea31a5add7a48736dc1822fca572c0..f5002015d82ea277c4e3e946a03e209a15f3eb64 100644 (file)
@@ -109,7 +109,7 @@ static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
 
 static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int res;
+       int i, res;
 
        BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
 
@@ -120,8 +120,8 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
                        freq_table[3].frequency = 1000000;
        }
        pr_info("db8500-cpufreq : Available frequencies:\n");
-       while (freq_table[i].frequency != CPUFREQ_TABLE_END)
-               pr_info("  %d Mhz\n", freq_table[i++].frequency/1000);
+       for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+               pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
 
        /* get policy fields based on the table */
        res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
index becd6d99203be3d1fffc84a6980f32d4fbed31ce..06ce2680d00d4ff33582d04cc9cb67eabf0bc442 100644 (file)
@@ -62,8 +62,9 @@ static int __cpuidle_register_device(struct cpuidle_device *dev);
 int cpuidle_idle_call(void)
 {
        struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+       struct cpuidle_driver *drv = cpuidle_get_driver();
        struct cpuidle_state *target_state;
-       int next_state;
+       int next_state, entered_state;
 
        if (off)
                return -ENODEV;
@@ -84,45 +85,36 @@ int cpuidle_idle_call(void)
        hrtimer_peek_ahead_timers();
 #endif
 
-       /*
-        * Call the device's prepare function before calling the
-        * governor's select function.  ->prepare gives the device's
-        * cpuidle driver a chance to update any dynamic information
-        * of its cpuidle states for the current idle period, e.g.
-        * state availability, latencies, residencies, etc.
-        */
-       if (dev->prepare)
-               dev->prepare(dev);
-
        /* ask the governor for the next state */
-       next_state = cpuidle_curr_governor->select(dev);
+       next_state = cpuidle_curr_governor->select(drv, dev);
        if (need_resched()) {
                local_irq_enable();
                return 0;
        }
 
-       target_state = &dev->states[next_state];
-
-       /* enter the state and update stats */
-       dev->last_state = target_state;
+       target_state = &drv->states[next_state];
 
        trace_power_start(POWER_CSTATE, next_state, dev->cpu);
        trace_cpu_idle(next_state, dev->cpu);
 
-       dev->last_residency = target_state->enter(dev, target_state);
+       entered_state = target_state->enter(dev, drv, next_state);
 
        trace_power_end(dev->cpu);
        trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
 
-       if (dev->last_state)
-               target_state = dev->last_state;
-
-       target_state->time += (unsigned long long)dev->last_residency;
-       target_state->usage++;
+       if (entered_state >= 0) {
+               /* Update cpuidle counters */
+               /* This can be moved to within driver enter routine
+                * but that results in multiple copies of same code.
+                */
+               dev->states_usage[entered_state].time +=
+                               (unsigned long long)dev->last_residency;
+               dev->states_usage[entered_state].usage++;
+       }
 
        /* give the governor an opportunity to reflect on the outcome */
        if (cpuidle_curr_governor->reflect)
-               cpuidle_curr_governor->reflect(dev);
+               cpuidle_curr_governor->reflect(dev, entered_state);
 
        return 0;
 }
@@ -173,11 +165,11 @@ void cpuidle_resume_and_unlock(void)
 EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
 
 #ifdef CONFIG_ARCH_HAS_CPU_RELAX
-static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
+static int poll_idle(struct cpuidle_device *dev,
+               struct cpuidle_driver *drv, int index)
 {
        ktime_t t1, t2;
        s64 diff;
-       int ret;
 
        t1 = ktime_get();
        local_irq_enable();
@@ -189,15 +181,14 @@ static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
        if (diff > INT_MAX)
                diff = INT_MAX;
 
-       ret = (int) diff;
-       return ret;
+       dev->last_residency = (int) diff;
+
+       return index;
 }
 
-static void poll_idle_init(struct cpuidle_device *dev)
+static void poll_idle_init(struct cpuidle_driver *drv)
 {
-       struct cpuidle_state *state = &dev->states[0];
-
-       cpuidle_set_statedata(state, NULL);
+       struct cpuidle_state *state = &drv->states[0];
 
        snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
        snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
@@ -208,7 +199,7 @@ static void poll_idle_init(struct cpuidle_device *dev)
        state->enter = poll_idle;
 }
 #else
-static void poll_idle_init(struct cpuidle_device *dev) {}
+static void poll_idle_init(struct cpuidle_driver *drv) {}
 #endif /* CONFIG_ARCH_HAS_CPU_RELAX */
 
 /**
@@ -235,21 +226,20 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
                        return ret;
        }
 
-       poll_idle_init(dev);
+       poll_idle_init(cpuidle_get_driver());
 
        if ((ret = cpuidle_add_state_sysfs(dev)))
                return ret;
 
        if (cpuidle_curr_governor->enable &&
-           (ret = cpuidle_curr_governor->enable(dev)))
+           (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
                goto fail_sysfs;
 
        for (i = 0; i < dev->state_count; i++) {
-               dev->states[i].usage = 0;
-               dev->states[i].time = 0;
+               dev->states_usage[i].usage = 0;
+               dev->states_usage[i].time = 0;
        }
        dev->last_residency = 0;
-       dev->last_state = NULL;
 
        smp_wmb();
 
@@ -283,7 +273,7 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
        dev->enabled = 0;
 
        if (cpuidle_curr_governor->disable)
-               cpuidle_curr_governor->disable(dev);
+               cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
 
        cpuidle_remove_state_sysfs(dev);
        enabled_devices--;
@@ -311,26 +301,6 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
 
        init_completion(&dev->kobj_unregister);
 
-       /*
-        * cpuidle driver should set the dev->power_specified bit
-        * before registering the device if the driver provides
-        * power_usage numbers.
-        *
-        * For those devices whose ->power_specified is not set,
-        * we fill in power_usage with decreasing values as the
-        * cpuidle code has an implicit assumption that state Cn
-        * uses less power than C(n-1).
-        *
-        * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
-        * an power value of -1.  So we use -2, -3, etc, for other
-        * c-states.
-        */
-       if (!dev->power_specified) {
-               int i;
-               for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
-                       dev->states[i].power_usage = -1 - i;
-       }
-
        per_cpu(cpuidle_devices, dev->cpu) = dev;
        list_add(&dev->device_list, &cpuidle_detected_devices);
        if ((ret = cpuidle_add_sysfs(sys_dev))) {
index 3f7e3cedd133b4ef66965351efb34351374b4af8..284d7af5a9c827ab227293fafd52cd27db442864 100644 (file)
 static struct cpuidle_driver *cpuidle_curr_driver;
 DEFINE_SPINLOCK(cpuidle_driver_lock);
 
+static void __cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+       int i;
+       /*
+        * cpuidle driver should set the drv->power_specified bit
+        * before registering if the driver provides
+        * power_usage numbers.
+        *
+        * If power_specified is not set,
+        * we fill in power_usage with decreasing values as the
+        * cpuidle code has an implicit assumption that state Cn
+        * uses less power than C(n-1).
+        *
+        * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
+        * an power value of -1.  So we use -2, -3, etc, for other
+        * c-states.
+        */
+       if (!drv->power_specified) {
+               for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
+                       drv->states[i].power_usage = -1 - i;
+       }
+}
+
+
 /**
  * cpuidle_register_driver - registers a driver
  * @drv: the driver
@@ -34,6 +58,7 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
                spin_unlock(&cpuidle_driver_lock);
                return -EBUSY;
        }
+       __cpuidle_register_driver(drv);
        cpuidle_curr_driver = drv;
        spin_unlock(&cpuidle_driver_lock);
 
index 3b8fce20f02362bb7dd04ccccab491e83d09e065..b6a09ea859b135c31e6dcffbad0e7a3d2ad66eee 100644 (file)
@@ -60,9 +60,11 @@ static inline void ladder_do_selection(struct ladder_device *ldev,
 
 /**
  * ladder_select_state - selects the next state to enter
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int ladder_select_state(struct cpuidle_device *dev)
+static int ladder_select_state(struct cpuidle_driver *drv,
+                               struct cpuidle_device *dev)
 {
        struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
        struct ladder_device_state *last_state;
@@ -77,15 +79,17 @@ static int ladder_select_state(struct cpuidle_device *dev)
 
        last_state = &ldev->states[last_idx];
 
-       if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
-               last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency;
+       if (drv->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) {
+               last_residency = cpuidle_get_last_residency(dev) - \
+                                        drv->states[last_idx].exit_latency;
+       }
        else
                last_residency = last_state->threshold.promotion_time + 1;
 
        /* consider promotion */
-       if (last_idx < dev->state_count - 1 &&
+       if (last_idx < drv->state_count - 1 &&
            last_residency > last_state->threshold.promotion_time &&
-           dev->states[last_idx + 1].exit_latency <= latency_req) {
+           drv->states[last_idx + 1].exit_latency <= latency_req) {
                last_state->stats.promotion_count++;
                last_state->stats.demotion_count = 0;
                if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
@@ -96,11 +100,11 @@ static int ladder_select_state(struct cpuidle_device *dev)
 
        /* consider demotion */
        if (last_idx > CPUIDLE_DRIVER_STATE_START &&
-           dev->states[last_idx].exit_latency > latency_req) {
+           drv->states[last_idx].exit_latency > latency_req) {
                int i;
 
                for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
-                       if (dev->states[i].exit_latency <= latency_req)
+                       if (drv->states[i].exit_latency <= latency_req)
                                break;
                }
                ladder_do_selection(ldev, last_idx, i);
@@ -123,9 +127,11 @@ static int ladder_select_state(struct cpuidle_device *dev)
 
 /**
  * ladder_enable_device - setup for the governor
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int ladder_enable_device(struct cpuidle_device *dev)
+static int ladder_enable_device(struct cpuidle_driver *drv,
+                               struct cpuidle_device *dev)
 {
        int i;
        struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
@@ -134,8 +140,8 @@ static int ladder_enable_device(struct cpuidle_device *dev)
 
        ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
 
-       for (i = 0; i < dev->state_count; i++) {
-               state = &dev->states[i];
+       for (i = 0; i < drv->state_count; i++) {
+               state = &drv->states[i];
                lstate = &ldev->states[i];
 
                lstate->stats.promotion_count = 0;
@@ -144,7 +150,7 @@ static int ladder_enable_device(struct cpuidle_device *dev)
                lstate->threshold.promotion_count = PROMOTION_COUNT;
                lstate->threshold.demotion_count = DEMOTION_COUNT;
 
-               if (i < dev->state_count - 1)
+               if (i < drv->state_count - 1)
                        lstate->threshold.promotion_time = state->exit_latency;
                if (i > 0)
                        lstate->threshold.demotion_time = state->exit_latency;
@@ -153,11 +159,24 @@ static int ladder_enable_device(struct cpuidle_device *dev)
        return 0;
 }
 
+/**
+ * ladder_reflect - update the correct last_state_idx
+ * @dev: the CPU
+ * @index: the index of actual state entered
+ */
+static void ladder_reflect(struct cpuidle_device *dev, int index)
+{
+       struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
+       if (index > 0)
+               ldev->last_state_idx = index;
+}
+
 static struct cpuidle_governor ladder_governor = {
        .name =         "ladder",
        .rating =       10,
        .enable =       ladder_enable_device,
        .select =       ladder_select_state,
+       .reflect =      ladder_reflect,
        .owner =        THIS_MODULE,
 };
 
index 00275244ce2f6885e885dcfa9dd810b32200bb7f..ad0952601ae2d2e322f6d5a81e42cc58545cc40e 100644 (file)
@@ -183,7 +183,7 @@ static inline int performance_multiplier(void)
 
 static DEFINE_PER_CPU(struct menu_device, menu_devices);
 
-static void menu_update(struct cpuidle_device *dev);
+static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
 
 /* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
 static u64 div_round64(u64 dividend, u32 divisor)
@@ -229,9 +229,10 @@ static void detect_repeating_patterns(struct menu_device *data)
 
 /**
  * menu_select - selects the next idle state to enter
+ * @drv: cpuidle driver containing state data
  * @dev: the CPU
  */
-static int menu_select(struct cpuidle_device *dev)
+static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
        struct menu_device *data = &__get_cpu_var(menu_devices);
        int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
@@ -241,7 +242,7 @@ static int menu_select(struct cpuidle_device *dev)
        struct timespec t;
 
        if (data->needs_update) {
-               menu_update(dev);
+               menu_update(drv, dev);
                data->needs_update = 0;
        }
 
@@ -286,11 +287,9 @@ static int menu_select(struct cpuidle_device *dev)
         * Find the idle state with the lowest power while satisfying
         * our constraints.
         */
-       for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
-               struct cpuidle_state *s = &dev->states[i];
+       for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
+               struct cpuidle_state *s = &drv->states[i];
 
-               if (s->flags & CPUIDLE_FLAG_IGNORE)
-                       continue;
                if (s->target_residency > data->predicted_us)
                        continue;
                if (s->exit_latency > latency_req)
@@ -311,26 +310,30 @@ static int menu_select(struct cpuidle_device *dev)
 /**
  * menu_reflect - records that data structures need update
  * @dev: the CPU
+ * @index: the index of actual entered state
  *
  * NOTE: it's important to be fast here because this operation will add to
  *       the overall exit latency.
  */
-static void menu_reflect(struct cpuidle_device *dev)
+static void menu_reflect(struct cpuidle_device *dev, int index)
 {
        struct menu_device *data = &__get_cpu_var(menu_devices);
-       data->needs_update = 1;
+       data->last_state_idx = index;
+       if (index >= 0)
+               data->needs_update = 1;
 }
 
 /**
  * menu_update - attempts to guess what happened after entry
+ * @drv: cpuidle driver containing state data
  * @dev: the CPU
  */
-static void menu_update(struct cpuidle_device *dev)
+static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
        struct menu_device *data = &__get_cpu_var(menu_devices);
        int last_idx = data->last_state_idx;
        unsigned int last_idle_us = cpuidle_get_last_residency(dev);
-       struct cpuidle_state *target = &dev->states[last_idx];
+       struct cpuidle_state *target = &drv->states[last_idx];
        unsigned int measured_us;
        u64 new_factor;
 
@@ -384,9 +387,11 @@ static void menu_update(struct cpuidle_device *dev)
 
 /**
  * menu_enable_device - scans a CPU's states and does setup
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int menu_enable_device(struct cpuidle_device *dev)
+static int menu_enable_device(struct cpuidle_driver *drv,
+                               struct cpuidle_device *dev)
 {
        struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
 
index be7917ec40c9f111270ca889ebdba3a25c61fb38..1e756e160dca0ff3d8d9fe25d74a57cdfff2be16 100644 (file)
@@ -216,7 +216,8 @@ static struct kobj_type ktype_cpuidle = {
 
 struct cpuidle_state_attr {
        struct attribute attr;
-       ssize_t (*show)(struct cpuidle_state *, char *);
+       ssize_t (*show)(struct cpuidle_state *, \
+                                       struct cpuidle_state_usage *, char *);
        ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
 };
 
@@ -224,19 +225,22 @@ struct cpuidle_state_attr {
 static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
 
 #define define_show_state_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+                        struct cpuidle_state_usage *state_usage, char *buf) \
 { \
        return sprintf(buf, "%u\n", state->_name);\
 }
 
 #define define_show_state_ull_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+                       struct cpuidle_state_usage *state_usage, char *buf) \
 { \
-       return sprintf(buf, "%llu\n", state->_name);\
+       return sprintf(buf, "%llu\n", state_usage->_name);\
 }
 
 #define define_show_state_str_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+                       struct cpuidle_state_usage *state_usage, char *buf) \
 { \
        if (state->_name[0] == '\0')\
                return sprintf(buf, "<null>\n");\
@@ -269,16 +273,18 @@ static struct attribute *cpuidle_state_default_attrs[] = {
 
 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
+#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
 static ssize_t cpuidle_state_show(struct kobject * kobj,
        struct attribute * attr ,char * buf)
 {
        int ret = -EIO;
        struct cpuidle_state *state = kobj_to_state(kobj);
+       struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
        struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
 
        if (cattr->show)
-               ret = cattr->show(state, buf);
+               ret = cattr->show(state, state_usage, buf);
 
        return ret;
 }
@@ -316,13 +322,15 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
 {
        int i, ret = -ENOMEM;
        struct cpuidle_state_kobj *kobj;
+       struct cpuidle_driver *drv = cpuidle_get_driver();
 
        /* state statistics */
        for (i = 0; i < device->state_count; i++) {
                kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
                if (!kobj)
                        goto error_state;
-               kobj->state = &device->states[i];
+               kobj->state = &drv->states[i];
+               kobj->state_usage = &device->states_usage[i];
                init_completion(&kobj->kobj_unregister);
 
                ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
index 5c6f56f21443ae7e01a1b9fc90b3202674fbaa37..dcd8babae9eb36fe864bae433558e5e1b4c77d83 100644 (file)
@@ -343,11 +343,13 @@ static void mv_process_hash_current(int first_block)
                else
                        op.config |= CFG_MID_FRAG;
 
-               writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A);
-               writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B);
-               writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C);
-               writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D);
-               writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E);
+               if (first_block) {
+                       writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A);
+                       writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B);
+                       writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C);
+                       writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D);
+                       writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E);
+               }
        }
 
        memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config));
index 643b055ed3cdc619d07166e8eaa84b2f849252df..8f0491037080df38856b76ec73db77cf18d3320f 100644 (file)
@@ -1,36 +1,29 @@
-config ARCH_HAS_DEVFREQ
-       bool
-       depends on ARCH_HAS_OPP
-       help
-         Denotes that the architecture supports DEVFREQ. If the architecture
-         supports multiple OPP entries per device and the frequency of the
-         devices with OPPs may be altered dynamically, the architecture
-         supports DEVFREQ.
-
 menuconfig PM_DEVFREQ
        bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support"
-       depends on PM_OPP && ARCH_HAS_DEVFREQ
        help
-         With OPP support, a device may have a list of frequencies and
-         voltages available. DEVFREQ, a generic DVFS framework can be
-         registered for a device with OPP support in order to let the
-         governor provided to DEVFREQ choose an operating frequency
-         based on the OPP's list and the policy given with DEVFREQ.
+         A device may have a list of frequencies and voltages available.
+         devfreq, a generic DVFS framework can be registered for a device
+         in order to let the governor provided to devfreq choose an
+         operating frequency based on the device driver's policy.
 
-         Each device may have its own governor and policy. DEVFREQ can
+         Each device may have its own governor and policy. Devfreq can
          reevaluate the device state periodically and/or based on the
-         OPP list changes (each frequency/voltage pair in OPP may be
-         disabled or enabled).
+         notification to "nb", a notifier block, of devfreq.
 
-         Like some CPUs with CPUFREQ, a device may have multiple clocks.
+         Like some CPUs with CPUfreq, a device may have multiple clocks.
          However, because the clock frequencies of a single device are
-         determined by the single device's state, an instance of DEVFREQ
+         determined by the single device's state, an instance of devfreq
          is attached to a single device and returns a "representative"
-         clock frequency from the OPP of the device, which is also attached
-         to a device by 1-to-1. The device registering DEVFREQ takes the
-         responsiblity to "interpret" the frequency listed in OPP and
+         clock frequency of the device, which is also attached
+         to a device by 1-to-1. The device registering devfreq takes the
+         responsiblity to "interpret" the representative frequency and
          to set its every clock accordingly with the "target" callback
-         given to DEVFREQ.
+         given to devfreq.
+
+         When OPP is used with the devfreq device, it is recommended to
+         register devfreq's nb to the OPP's notifier head.  If OPP is
+         used with the devfreq device, you may use OPP helper
+         functions defined in devfreq.h.
 
 if PM_DEVFREQ
 
index 5d15b812377bc9ad23420e6d41bd7ea62dc62e2f..59d24e9cb8c512a949a24803c5bf11a143fc649d 100644 (file)
@@ -15,7 +15,9 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/opp.h>
 #include <linux/devfreq.h>
 #include <linux/workqueue.h>
@@ -416,10 +418,14 @@ out:
  */
 int devfreq_remove_device(struct devfreq *devfreq)
 {
+       bool central_polling;
+
        if (!devfreq)
                return -EINVAL;
 
-       if (!devfreq->governor->no_central_polling) {
+       central_polling = !devfreq->governor->no_central_polling;
+
+       if (central_polling) {
                mutex_lock(&devfreq_list_lock);
                while (wait_remove_device == devfreq) {
                        mutex_unlock(&devfreq_list_lock);
@@ -431,7 +437,7 @@ int devfreq_remove_device(struct devfreq *devfreq)
        mutex_lock(&devfreq->lock);
        _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
 
-       if (!devfreq->governor->no_central_polling)
+       if (central_polling)
                mutex_unlock(&devfreq_list_lock);
 
        return 0;
index 8af8e864a9cffbc13c91c625a837e11bb8de24fe..73464a62adf74ae1483a16ad71847c03fc03169f 100644 (file)
@@ -1128,7 +1128,7 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {
        { .compatible = "fsl,p1020-memory-controller", },
        { .compatible = "fsl,p1021-memory-controller", },
        { .compatible = "fsl,p2020-memory-controller", },
-       { .compatible = "fsl,p4080-memory-controller", },
+       { .compatible = "fsl,qoriq-memory-controller", },
        {},
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
index bcb1126e3d00b2357a0c5748edbd8b1b470c0423..153980be4ee64462f12a97563c0143fc59b3eb82 100644 (file)
@@ -585,14 +585,12 @@ int dmi_name_in_serial(const char *str)
 }
 
 /**
- *     dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information.
+ *     dmi_name_in_vendors - Check if string is in the DMI system or board vendor name
  *     @str:   Case sensitive Name
  */
 int dmi_name_in_vendors(const char *str)
 {
-       static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR,
-                               DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR,
-                               DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE };
+       static int fields[] = { DMI_SYS_VENDOR, DMI_BOARD_VENDOR, DMI_NONE };
        int i;
        for (i = 0; fields[i] != DMI_NONE; i++) {
                int f = fields[i];
index 8370f72d87ff5ed955789973845629f406f6734e..b0a81173a268175f71606e1aad2ab6067b67f698 100644 (file)
@@ -457,7 +457,8 @@ static int efi_pstore_close(struct pstore_info *psi)
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-                              struct timespec *timespec, struct pstore_info *psi)
+                              struct timespec *timespec,
+                              char **buf, struct pstore_info *psi)
 {
        efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
        struct efivars *efivars = psi->data;
@@ -478,7 +479,11 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
                                timespec->tv_nsec = 0;
                                get_var_data_locked(efivars, &efivars->walk_entry->var);
                                size = efivars->walk_entry->var.DataSize;
-                               memcpy(psi->buf, efivars->walk_entry->var.Data, size);
+                               *buf = kmalloc(size, GFP_KERNEL);
+                               if (*buf == NULL)
+                                       return -ENOMEM;
+                               memcpy(*buf, efivars->walk_entry->var.Data,
+                                      size);
                                efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
                                                   struct efivar_entry, list);
                                return size;
@@ -576,7 +581,8 @@ static int efi_pstore_close(struct pstore_info *psi)
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-                              struct timespec *time, struct pstore_info *psi)
+                              struct timespec *timespec,
+                              char **buf, struct pstore_info *psi)
 {
        return -1;
 }
index 0e49d87f6c60c7b35df327dafd235a394cbb07e5..0b0562979171065bb3c454112c985cb74a633728 100644 (file)
@@ -148,13 +148,17 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
        return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
 }
 
-#define MOD_REG_BIT(reg, bit_mask, set)        \
-do {   \
-       int l = __raw_readl(base + reg); \
-       if (set) l |= bit_mask; \
-       else l &= ~bit_mask; \
-       __raw_writel(l, base + reg); \
-} while(0)
+static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
+{
+       int l = __raw_readl(base + reg);
+
+       if (set) 
+               l |= mask;
+       else
+               l &= ~mask;
+
+       __raw_writel(l, base + reg);
+}
 
 /**
  * _set_gpio_debounce - low level gpio debounce time
@@ -210,28 +214,28 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
        u32 gpio_bit = 1 << gpio;
 
        if (cpu_is_omap44xx()) {
-               MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_LOW);
-               MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_HIGH);
-               MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_RISING);
-               MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_FALLING);
+               _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT0, gpio_bit,
+                         trigger & IRQ_TYPE_LEVEL_LOW);
+               _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT1, gpio_bit,
+                         trigger & IRQ_TYPE_LEVEL_HIGH);
+               _gpio_rmw(base, OMAP4_GPIO_RISINGDETECT, gpio_bit,
+                         trigger & IRQ_TYPE_EDGE_RISING);
+               _gpio_rmw(base, OMAP4_GPIO_FALLINGDETECT, gpio_bit,
+                         trigger & IRQ_TYPE_EDGE_FALLING);
        } else {
-               MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_LOW);
-               MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_HIGH);
-               MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_RISING);
-               MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_FALLING);
+               _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
+                         trigger & IRQ_TYPE_LEVEL_LOW);
+               _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
+                         trigger & IRQ_TYPE_LEVEL_HIGH);
+               _gpio_rmw(base, OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
+                         trigger & IRQ_TYPE_EDGE_RISING);
+               _gpio_rmw(base, OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
+                         trigger & IRQ_TYPE_EDGE_FALLING);
        }
        if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
                if (cpu_is_omap44xx()) {
-                       MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit,
-                               trigger != 0);
+                       _gpio_rmw(base, OMAP4_GPIO_IRQWAKEN0, gpio_bit,
+                                 trigger != 0);
                } else {
                        /*
                         * GPIO wakeup request can only be generated on edge
@@ -1086,6 +1090,11 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
 
        gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
                                    handle_simple_irq);
+       if (!gc) {
+               dev_err(bank->dev, "Memory alloc failed for gc\n");
+               return;
+       }
+
        ct = gc->chip_types;
 
        /* NOTE: No ack required, reading IRQ status clears it. */
index 0550dcb85814026b9e759abd4c8a81d83b02f9cc..d3f3e8f5456129e7036fc3737181d37b40b8c642 100644 (file)
@@ -546,7 +546,7 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip)
  * Translate OpenFirmware node properties into platform_data
  * WARNING: This is DEPRECATED and will be removed eventually!
  */
-void
+static void
 pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
 {
        struct device_node *node;
@@ -574,7 +574,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
                *invert = *val;
 }
 #else
-void
+static void
 pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
 {
        *gpio_base = -1;
@@ -596,9 +596,6 @@ static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
 
        /* set platform specific polarity inversion */
        ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
-       if (ret)
-               goto out;
-       return 0;
 out:
        return ret;
 }
@@ -640,7 +637,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
        struct pca953x_platform_data *pdata;
        struct pca953x_chip *chip;
        int irq_base=0, invert=0;
-       int ret = 0;
+       int ret;
 
        chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
        if (chip == NULL)
@@ -673,10 +670,10 @@ static int __devinit pca953x_probe(struct i2c_client *client,
        pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
 
        if (chip->chip_type == PCA953X_TYPE)
-               device_pca953x_init(chip, invert);
-       else if (chip->chip_type == PCA957X_TYPE)
-               device_pca957x_init(chip, invert);
+               ret = device_pca953x_init(chip, invert);
        else
+               ret = device_pca957x_init(chip, invert);
+       if (ret)
                goto out_failed;
 
        ret = pca953x_irq_setup(chip, id, irq_base);
index 785127cb281b8759b7dd77ab240aedc113621f61..1368826ef28475c0f191510b7016dd1068b55187 100644 (file)
@@ -9,7 +9,6 @@ menuconfig DRM
        depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
        select I2C
        select I2C_ALGOBIT
-       select SLOW_WORK
        help
          Kernel-level support for the Direct Rendering Infrastructure (DRI)
          introduced in XFree86 4.0. If you say Y here, you need to select
@@ -96,6 +95,7 @@ config DRM_I915
        select FB_CFB_IMAGEBLIT
        # i915 depends on ACPI_VIDEO when ACPI is enabled
        # but for select to work, need to select ACPI_VIDEO's dependencies, ick
+       select BACKLIGHT_LCD_SUPPORT if ACPI
        select BACKLIGHT_CLASS_DEVICE if ACPI
        select VIDEO_OUTPUT_CONTROL if ACPI
        select INPUT if ACPI
index 711d9653abd08f1f436b2977a5a5514a1ce0c43f..8323fc3898401ac957d9a677b947455f5a598b91 100644 (file)
@@ -163,6 +163,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
        { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
        { DRM_MODE_CONNECTOR_TV, "TV", 0 },
        { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
+       { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
@@ -171,6 +172,7 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] =
        { DRM_MODE_ENCODER_TMDS, "TMDS" },
        { DRM_MODE_ENCODER_LVDS, "LVDS" },
        { DRM_MODE_ENCODER_TVDAC, "TV" },
+       { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
 };
 
 char *drm_get_encoder_name(struct drm_encoder *encoder)
@@ -464,8 +466,10 @@ void drm_connector_init(struct drm_device *dev,
        list_add_tail(&connector->head, &dev->mode_config.connector_list);
        dev->mode_config.num_connector++;
 
-       drm_connector_attach_property(connector,
-                                     dev->mode_config.edid_property, 0);
+       if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+               drm_connector_attach_property(connector,
+                                             dev->mode_config.edid_property,
+                                             0);
 
        drm_connector_attach_property(connector,
                                      dev->mode_config.dpms_property, 0);
@@ -1869,6 +1873,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        }
 
        if (num_clips && clips_ptr) {
+               if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
+                       ret = -EINVAL;
+                       goto out_err1;
+               }
                clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
                if (!clips) {
                        ret = -ENOMEM;
@@ -2114,8 +2122,10 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
        property->num_values = num_values;
        INIT_LIST_HEAD(&property->enum_blob_list);
 
-       if (name)
+       if (name) {
                strncpy(property->name, name, DRM_PROP_NAME_LEN);
+               property->name[DRM_PROP_NAME_LEN-1] = '\0';
+       }
 
        list_add_tail(&property->head, &dev->mode_config.property_list);
        return property;
index 2957636161e837c61aa9f42cc243738739b6bc10..3969f7553fe75bf5fa877020e3ccea53f150dfd8 100644 (file)
@@ -484,6 +484,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        struct drm_connector *save_connectors, *connector;
        int count = 0, ro, fail = 0;
        struct drm_crtc_helper_funcs *crtc_funcs;
+       struct drm_mode_set save_set;
        int ret = 0;
        int i;
 
@@ -556,6 +557,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                save_connectors[count++] = *connector;
        }
 
+       save_set.crtc = set->crtc;
+       save_set.mode = &set->crtc->mode;
+       save_set.x = set->crtc->x;
+       save_set.y = set->crtc->y;
+       save_set.fb = set->crtc->fb;
+
        /* We should be able to check here if the fb has the same properties
         * and then just flip_or_move it */
        if (set->crtc->fb != set->fb) {
@@ -721,6 +728,12 @@ fail:
                *connector = save_connectors[count++];
        }
 
+       /* Try to restore the config */
+       if (mode_changed &&
+           !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
+                                     save_set.y, save_set.fb))
+               DRM_ERROR("failed to restore config after modeset failure\n");
+
        kfree(save_connectors);
        kfree(save_encoders);
        kfree(save_crtcs);
index d067c12ba9400d51ef41af0948a93f92d54f611b..1c7a1c0d3edd9aa34d7530e04fa5b482a9d07973 100644 (file)
@@ -118,7 +118,10 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
                tmp->minor = minor;
                tmp->dent = ent;
                tmp->info_ent = &files[i];
-               list_add(&(tmp->list), &(minor->debugfs_nodes.list));
+
+               mutex_lock(&minor->debugfs_lock);
+               list_add(&tmp->list, &minor->debugfs_list);
+               mutex_unlock(&minor->debugfs_lock);
        }
        return 0;
 
@@ -146,7 +149,8 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
        char name[64];
        int ret;
 
-       INIT_LIST_HEAD(&minor->debugfs_nodes.list);
+       INIT_LIST_HEAD(&minor->debugfs_list);
+       mutex_init(&minor->debugfs_lock);
        sprintf(name, "%d", minor_id);
        minor->debugfs_root = debugfs_create_dir(name, root);
        if (!minor->debugfs_root) {
@@ -192,8 +196,9 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count,
        struct drm_info_node *tmp;
        int i;
 
+       mutex_lock(&minor->debugfs_lock);
        for (i = 0; i < count; i++) {
-               list_for_each_safe(pos, q, &minor->debugfs_nodes.list) {
+               list_for_each_safe(pos, q, &minor->debugfs_list) {
                        tmp = list_entry(pos, struct drm_info_node, list);
                        if (tmp->info_ent == &files[i]) {
                                debugfs_remove(tmp->dent);
@@ -202,6 +207,7 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count,
                        }
                }
        }
+       mutex_unlock(&minor->debugfs_lock);
        return 0;
 }
 EXPORT_SYMBOL(drm_debugfs_remove_files);
index fc81af9dbf42d1a3522b98fa9620f3240a1978b2..40c187c60f44fcb2ea45bedede0fe003f9e8ebb2 100644 (file)
@@ -125,7 +125,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
-       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
 
        DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
 
index cb3794a00f98c541264404164f0eba269736126b..44a5d0ad8b7c56e99c9ce85f2dfcf14d19e855e0 100644 (file)
@@ -110,10 +110,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
        /* Prevent vblank irq processing while disabling vblank irqs,
         * so no updates of timestamps or count can happen after we've
         * disabled. Needed to prevent races in case of delayed irq's.
-        * Disable preemption, so vblank_time_lock is held as short as
-        * possible, even under a kernel with PREEMPT_RT patches.
         */
-       preempt_disable();
        spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
 
        dev->driver->disable_vblank(dev, crtc);
@@ -164,7 +161,6 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
        clear_vblank_timestamps(dev, crtc);
 
        spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
-       preempt_enable();
 }
 
 static void vblank_disable_fn(unsigned long arg)
@@ -407,13 +403,16 @@ int drm_irq_uninstall(struct drm_device *dev)
        /*
         * Wake up any waiters so they don't hang.
         */
-       spin_lock_irqsave(&dev->vbl_lock, irqflags);
-       for (i = 0; i < dev->num_crtcs; i++) {
-               DRM_WAKEUP(&dev->vbl_queue[i]);
-               dev->vblank_enabled[i] = 0;
-               dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
+       if (dev->num_crtcs) {
+               spin_lock_irqsave(&dev->vbl_lock, irqflags);
+               for (i = 0; i < dev->num_crtcs; i++) {
+                       DRM_WAKEUP(&dev->vbl_queue[i]);
+                       dev->vblank_enabled[i] = 0;
+                       dev->last_vblank[i] =
+                               dev->driver->get_vblank_counter(dev, i);
+               }
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
        }
-       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
        if (!irq_enabled)
                return -EINVAL;
@@ -886,10 +885,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        /* Going from 0->1 means we have to enable interrupts again */
        if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
-               /* Disable preemption while holding vblank_time_lock. Do
-                * it explicitely to guard against PREEMPT_RT kernel.
-                */
-               preempt_disable();
                spin_lock_irqsave(&dev->vblank_time_lock, irqflags2);
                if (!dev->vblank_enabled[crtc]) {
                        /* Enable vblank irqs under vblank_time_lock protection.
@@ -909,7 +904,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
                        }
                }
                spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
-               preempt_enable();
        } else {
                if (!dev->vblank_enabled[crtc]) {
                        atomic_dec(&dev->vblank_refcount[crtc]);
@@ -1125,6 +1119,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
                trace_drm_vblank_event_delivered(current->pid, pipe,
                                                 vblwait->request.sequence);
        } else {
+               /* drm_handle_vblank_events will call drm_vblank_put */
                list_add_tail(&e->base.link, &dev->vblank_event_list);
                vblwait->reply.sequence = vblwait->request.sequence;
        }
@@ -1205,8 +1200,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
                goto done;
        }
 
-       if (flags & _DRM_VBLANK_EVENT)
+       if (flags & _DRM_VBLANK_EVENT) {
+               /* must hold on to the vblank ref until the event fires
+                * drm_vblank_put will be called asynchronously
+                */
                return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
+       }
 
        if ((flags & _DRM_VBLANK_NEXTONMISS) &&
            (seq - vblwait->request.sequence) <= (1<<23)) {
index 6f8afea94fc979b74476746aca1ae32341846357..2bb07bca511a12b6949892186565cfde960db8ca 100644 (file)
 #include "drm.h"
 
 #include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
 #include "exynos_drm_buf.h"
 
-static DEFINE_MUTEX(exynos_drm_buf_lock);
-
 static int lowlevel_buffer_allocate(struct drm_device *dev,
-               struct exynos_drm_buf_entry *entry)
+               struct exynos_drm_gem_buf *buffer)
 {
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       entry->vaddr = dma_alloc_writecombine(dev->dev, entry->size,
-                       (dma_addr_t *)&entry->paddr, GFP_KERNEL);
-       if (!entry->paddr) {
+       buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size,
+                       &buffer->dma_addr, GFP_KERNEL);
+       if (!buffer->kvaddr) {
                DRM_ERROR("failed to allocate buffer.\n");
                return -ENOMEM;
        }
 
-       DRM_DEBUG_KMS("allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n",
-                       (unsigned int)entry->vaddr, entry->paddr, entry->size);
+       DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
+                       (unsigned long)buffer->kvaddr,
+                       (unsigned long)buffer->dma_addr,
+                       buffer->size);
 
        return 0;
 }
 
 static void lowlevel_buffer_deallocate(struct drm_device *dev,
-               struct exynos_drm_buf_entry *entry)
+               struct exynos_drm_gem_buf *buffer)
 {
        DRM_DEBUG_KMS("%s.\n", __FILE__);
 
-       if (entry->paddr && entry->vaddr && entry->size)
-               dma_free_writecombine(dev->dev, entry->size, entry->vaddr,
-                               entry->paddr);
+       if (buffer->dma_addr && buffer->size)
+               dma_free_writecombine(dev->dev, buffer->size, buffer->kvaddr,
+                               (dma_addr_t)buffer->dma_addr);
        else
-               DRM_DEBUG_KMS("entry data is null.\n");
+               DRM_DEBUG_KMS("buffer data are invalid.\n");
 }
 
-struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
+struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
                unsigned int size)
 {
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
 
        DRM_DEBUG_KMS("%s.\n", __FILE__);
+       DRM_DEBUG_KMS("desired size = 0x%x\n", size);
 
-       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-       if (!entry) {
-               DRM_ERROR("failed to allocate exynos_drm_buf_entry.\n");
+       buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+       if (!buffer) {
+               DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       entry->size = size;
+       buffer->size = size;
 
        /*
         * allocate memory region with size and set the memory information
-        * to vaddr and paddr of a entry object.
+        * to vaddr and dma_addr of a buffer object.
         */
-       if (lowlevel_buffer_allocate(dev, entry) < 0) {
-               kfree(entry);
-               entry = NULL;
+       if (lowlevel_buffer_allocate(dev, buffer) < 0) {
+               kfree(buffer);
+               buffer = NULL;
                return ERR_PTR(-ENOMEM);
        }
 
-       return entry;
+       return buffer;
 }
 
 void exynos_drm_buf_destroy(struct drm_device *dev,
-               struct exynos_drm_buf_entry *entry)
+               struct exynos_drm_gem_buf *buffer)
 {
        DRM_DEBUG_KMS("%s.\n", __FILE__);
 
-       if (!entry) {
-               DRM_DEBUG_KMS("entry is null.\n");
+       if (!buffer) {
+               DRM_DEBUG_KMS("buffer is null.\n");
                return;
        }
 
-       lowlevel_buffer_deallocate(dev, entry);
+       lowlevel_buffer_deallocate(dev, buffer);
 
-       kfree(entry);
-       entry = NULL;
+       kfree(buffer);
+       buffer = NULL;
 }
 
 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
index 045d59eab01a29b5270410d661968d408dcfa663..6e91f9caa5dbdfe12aade5461c3ad253888f20bf 100644 (file)
 #ifndef _EXYNOS_DRM_BUF_H_
 #define _EXYNOS_DRM_BUF_H_
 
-/*
- * exynos drm buffer entry structure.
- *
- * @paddr: physical address of allocated memory.
- * @vaddr: kernel virtual address of allocated memory.
- * @size: size of allocated memory.
- */
-struct exynos_drm_buf_entry {
-       dma_addr_t paddr;
-       void __iomem *vaddr;
-       unsigned int size;
-};
-
 /* allocate physical memory. */
-struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
+struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
                unsigned int size);
 
-/* get physical memory information of a drm framebuffer. */
-struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
+/* get memory information of a drm framebuffer. */
+struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
 
 /* remove allocated physical memory. */
 void exynos_drm_buf_destroy(struct drm_device *dev,
-               struct exynos_drm_buf_entry *entry);
+               struct exynos_drm_gem_buf *buffer);
 
 #endif
index 985d9e7687287d915c6a76e2b7219f9e7840e7f8..d620b0784257f05cab7c52b121a460c99f6f7daf 100644 (file)
@@ -37,6 +37,8 @@
 
 struct exynos_drm_connector {
        struct drm_connector    drm_connector;
+       uint32_t                encoder_id;
+       struct exynos_drm_manager *manager;
 };
 
 /* convert exynos_video_timings to drm_display_mode */
@@ -47,6 +49,7 @@ convert_to_display_mode(struct drm_display_mode *mode,
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        mode->clock = timing->pixclock / 1000;
+       mode->vrefresh = timing->refresh;
 
        mode->hdisplay = timing->xres;
        mode->hsync_start = mode->hdisplay + timing->left_margin;
@@ -57,6 +60,12 @@ convert_to_display_mode(struct drm_display_mode *mode,
        mode->vsync_start = mode->vdisplay + timing->upper_margin;
        mode->vsync_end = mode->vsync_start + timing->vsync_len;
        mode->vtotal = mode->vsync_end + timing->lower_margin;
+
+       if (timing->vmode & FB_VMODE_INTERLACED)
+               mode->flags |= DRM_MODE_FLAG_INTERLACE;
+
+       if (timing->vmode & FB_VMODE_DOUBLE)
+               mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 }
 
 /* convert drm_display_mode to exynos_video_timings */
@@ -69,7 +78,7 @@ convert_to_video_timing(struct fb_videomode *timing,
        memset(timing, 0, sizeof(*timing));
 
        timing->pixclock = mode->clock * 1000;
-       timing->refresh = mode->vrefresh;
+       timing->refresh = drm_mode_vrefresh(mode);
 
        timing->xres = mode->hdisplay;
        timing->left_margin = mode->hsync_start - mode->hdisplay;
@@ -92,15 +101,16 @@ convert_to_video_timing(struct fb_videomode *timing,
 
 static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 {
-       struct exynos_drm_manager *manager =
-                               exynos_drm_get_manager(connector->encoder);
-       struct exynos_drm_display *display = manager->display;
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct exynos_drm_manager *manager = exynos_connector->manager;
+       struct exynos_drm_display_ops *display_ops = manager->display_ops;
        unsigned int count;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (!display) {
-               DRM_DEBUG_KMS("display is null.\n");
+       if (!display_ops) {
+               DRM_DEBUG_KMS("display_ops is null.\n");
                return 0;
        }
 
@@ -112,7 +122,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
         * P.S. in case of lcd panel, count is always 1 if success
         * because lcd panel has only one mode.
         */
-       if (display->get_edid) {
+       if (display_ops->get_edid) {
                int ret;
                void *edid;
 
@@ -122,7 +132,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
                        return 0;
                }
 
-               ret = display->get_edid(manager->dev, connector,
+               ret = display_ops->get_edid(manager->dev, connector,
                                                edid, MAX_EDID);
                if (ret < 0) {
                        DRM_ERROR("failed to get edid data.\n");
@@ -140,8 +150,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
                struct drm_display_mode *mode = drm_mode_create(connector->dev);
                struct fb_videomode *timing;
 
-               if (display->get_timing)
-                       timing = display->get_timing(manager->dev);
+               if (display_ops->get_timing)
+                       timing = display_ops->get_timing(manager->dev);
                else {
                        drm_mode_destroy(connector->dev, mode);
                        return 0;
@@ -162,9 +172,10 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
                                            struct drm_display_mode *mode)
 {
-       struct exynos_drm_manager *manager =
-                               exynos_drm_get_manager(connector->encoder);
-       struct exynos_drm_display *display = manager->display;
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct exynos_drm_manager *manager = exynos_connector->manager;
+       struct exynos_drm_display_ops *display_ops = manager->display_ops;
        struct fb_videomode timing;
        int ret = MODE_BAD;
 
@@ -172,8 +183,8 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
 
        convert_to_video_timing(&timing, mode);
 
-       if (display && display->check_timing)
-               if (!display->check_timing(manager->dev, (void *)&timing))
+       if (display_ops && display_ops->check_timing)
+               if (!display_ops->check_timing(manager->dev, (void *)&timing))
                        ret = MODE_OK;
 
        return ret;
@@ -181,9 +192,25 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
 
 struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
 {
+       struct drm_device *dev = connector->dev;
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct drm_mode_object *obj;
+       struct drm_encoder *encoder;
+
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       return connector->encoder;
+       obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
+                                  DRM_MODE_OBJECT_ENCODER);
+       if (!obj) {
+               DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
+                               exynos_connector->encoder_id);
+               return NULL;
+       }
+
+       encoder = obj_to_encoder(obj);
+
+       return encoder;
 }
 
 static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
@@ -196,15 +223,17 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
 static enum drm_connector_status
 exynos_drm_connector_detect(struct drm_connector *connector, bool force)
 {
-       struct exynos_drm_manager *manager =
-                               exynos_drm_get_manager(connector->encoder);
-       struct exynos_drm_display *display = manager->display;
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct exynos_drm_manager *manager = exynos_connector->manager;
+       struct exynos_drm_display_ops *display_ops =
+                                       manager->display_ops;
        enum drm_connector_status status = connector_status_disconnected;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (display && display->is_connected) {
-               if (display->is_connected(manager->dev))
+       if (display_ops && display_ops->is_connected) {
+               if (display_ops->is_connected(manager->dev))
                        status = connector_status_connected;
                else
                        status = connector_status_disconnected;
@@ -251,9 +280,11 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 
        connector = &exynos_connector->drm_connector;
 
-       switch (manager->display->type) {
+       switch (manager->display_ops->type) {
        case EXYNOS_DISPLAY_TYPE_HDMI:
                type = DRM_MODE_CONNECTOR_HDMIA;
+               connector->interlace_allowed = true;
+               connector->polled = DRM_CONNECTOR_POLL_HPD;
                break;
        default:
                type = DRM_MODE_CONNECTOR_Unknown;
@@ -267,7 +298,10 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
        if (err)
                goto err_connector;
 
+       exynos_connector->encoder_id = encoder->base.id;
+       exynos_connector->manager = manager;
        connector->encoder = encoder;
+
        err = drm_mode_connector_attach_encoder(connector, encoder);
        if (err) {
                DRM_ERROR("failed to attach a connector to a encoder\n");
index 9337e5e2dbb6204428178c8c3a962ebb3d61fab0..ee43cc22085304f7f07f267cd63a7d2be05d249a 100644 (file)
 #include "drmP.h"
 #include "drm_crtc_helper.h"
 
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_encoder.h"
+#include "exynos_drm_gem.h"
 #include "exynos_drm_buf.h"
 
 #define to_exynos_crtc(x)      container_of(x, struct exynos_drm_crtc,\
                                drm_crtc)
 
-/*
- * Exynos specific crtc postion structure.
- *
- * @fb_x: offset x on a framebuffer to be displyed
- *     - the unit is screen coordinates.
- * @fb_y: offset y on a framebuffer to be displayed
- *     - the unit is screen coordinates.
- * @crtc_x: offset x on hardware screen.
- * @crtc_y: offset y on hardware screen.
- * @crtc_w: width of hardware screen.
- * @crtc_h: height of hardware screen.
- */
-struct exynos_drm_crtc_pos {
-       unsigned int fb_x;
-       unsigned int fb_y;
-       unsigned int crtc_x;
-       unsigned int crtc_y;
-       unsigned int crtc_w;
-       unsigned int crtc_h;
-};
-
 /*
  * Exynos specific crtc structure.
  *
@@ -85,30 +66,31 @@ static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
 
        exynos_drm_fn_encoder(crtc, overlay,
                        exynos_drm_encoder_crtc_mode_set);
-       exynos_drm_fn_encoder(crtc, NULL, exynos_drm_encoder_crtc_commit);
+       exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                       exynos_drm_encoder_crtc_commit);
 }
 
-static int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
-                                      struct drm_framebuffer *fb,
-                                      struct drm_display_mode *mode,
-                                      struct exynos_drm_crtc_pos *pos)
+int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+                             struct drm_framebuffer *fb,
+                             struct drm_display_mode *mode,
+                             struct exynos_drm_crtc_pos *pos)
 {
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
        unsigned int actual_w;
        unsigned int actual_h;
 
-       entry = exynos_drm_fb_get_buf(fb);
-       if (!entry) {
-               DRM_LOG_KMS("entry is null.\n");
+       buffer = exynos_drm_fb_get_buf(fb);
+       if (!buffer) {
+               DRM_LOG_KMS("buffer is null.\n");
                return -EFAULT;
        }
 
-       overlay->paddr = entry->paddr;
-       overlay->vaddr = entry->vaddr;
+       overlay->dma_addr = buffer->dma_addr;
+       overlay->vaddr = buffer->kvaddr;
 
-       DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
+       DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
                        (unsigned long)overlay->vaddr,
-                       (unsigned long)overlay->paddr);
+                       (unsigned long)overlay->dma_addr);
 
        actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
        actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
@@ -171,9 +153,26 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc)
 
 static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
-       DRM_DEBUG_KMS("%s\n", __FILE__);
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 
-       /* TODO */
+       DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                               exynos_drm_encoder_crtc_commit);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               /* TODO */
+               exynos_drm_fn_encoder(crtc, NULL,
+                               exynos_drm_encoder_crtc_disable);
+               break;
+       default:
+               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+               break;
+       }
 }
 
 static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
@@ -185,9 +184,12 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
 
 static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
 {
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       /* drm framework doesn't check NULL. */
+       exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                       exynos_drm_encoder_crtc_commit);
 }
 
 static bool
index c584042d6d2cb21c8282975f9edf28898b4e56e0..25f72a62cb880b757b54e0514693eedd624ce27b 100644 (file)
@@ -35,4 +35,29 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
 int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
 void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
 
+/*
+ * Exynos specific crtc postion structure.
+ *
+ * @fb_x: offset x on a framebuffer to be displyed
+ *     - the unit is screen coordinates.
+ * @fb_y: offset y on a framebuffer to be displayed
+ *     - the unit is screen coordinates.
+ * @crtc_x: offset x on hardware screen.
+ * @crtc_y: offset y on hardware screen.
+ * @crtc_w: width of hardware screen.
+ * @crtc_h: height of hardware screen.
+ */
+struct exynos_drm_crtc_pos {
+       unsigned int fb_x;
+       unsigned int fb_y;
+       unsigned int crtc_x;
+       unsigned int crtc_y;
+       unsigned int crtc_w;
+       unsigned int crtc_h;
+};
+
+int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+                             struct drm_framebuffer *fb,
+                             struct drm_display_mode *mode,
+                             struct exynos_drm_crtc_pos *pos);
 #endif
index 83810cbe3c1770aeea62814dfdd98c2e1b33df2e..53e2216de61dd5c42c35eaa7f0c23ca1e991a621 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "drmP.h"
 #include "drm.h"
+#include "drm_crtc_helper.h"
 
 #include <drm/exynos_drm.h>
 
@@ -61,6 +62,9 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
        drm_mode_config_init(dev);
 
+       /* init kms poll for handling hpd */
+       drm_kms_helper_poll_init(dev);
+
        exynos_drm_mode_config_init(dev);
 
        /*
@@ -116,6 +120,7 @@ static int exynos_drm_unload(struct drm_device *dev)
        exynos_drm_fbdev_fini(dev);
        exynos_drm_device_unregister(dev);
        drm_vblank_cleanup(dev);
+       drm_kms_helper_poll_fini(dev);
        drm_mode_config_cleanup(dev);
        kfree(dev->dev_private);
 
index c03683f2ae72dffb084aaede5dba582a68c835f9..5e02e6ecc2e026955c9bf88bd5461bf893c1dbec 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef _EXYNOS_DRM_DRV_H_
 #define _EXYNOS_DRM_DRV_H_
 
+#include <linux/module.h>
 #include "drm.h"
 
 #define MAX_CRTC       2
@@ -79,8 +80,8 @@ struct exynos_drm_overlay_ops {
  * @scan_flag: interlace or progressive way.
  *     (it could be DRM_MODE_FLAG_*)
  * @bpp: pixel size.(in bit)
- * @paddr: bus(accessed by dma) physical memory address to this overlay
- *             and this is physically continuous.
+ * @dma_addr: bus(accessed by dma) address to the memory region allocated
+ *     for a overlay.
  * @vaddr: virtual memory addresss to this overlay.
  * @default_win: a window to be enabled.
  * @color_key: color key on or off.
@@ -108,7 +109,7 @@ struct exynos_drm_overlay {
        unsigned int scan_flag;
        unsigned int bpp;
        unsigned int pitch;
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
        void __iomem *vaddr;
 
        bool default_win;
@@ -130,7 +131,7 @@ struct exynos_drm_overlay {
  * @check_timing: check if timing is valid or not.
  * @power_on: display device on or off.
  */
-struct exynos_drm_display {
+struct exynos_drm_display_ops {
        enum exynos_drm_output_type type;
        bool (*is_connected)(struct device *dev);
        int (*get_edid)(struct device *dev, struct drm_connector *connector,
@@ -146,12 +147,14 @@ struct exynos_drm_display {
  * @mode_set: convert drm_display_mode to hw specific display mode and
  *           would be called by encoder->mode_set().
  * @commit: set current hw specific display mode to hw.
+ * @disable: disable hardware specific display mode.
  * @enable_vblank: specific driver callback for enabling vblank interrupt.
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
  */
 struct exynos_drm_manager_ops {
        void (*mode_set)(struct device *subdrv_dev, void *mode);
        void (*commit)(struct device *subdrv_dev);
+       void (*disable)(struct device *subdrv_dev);
        int (*enable_vblank)(struct device *subdrv_dev);
        void (*disable_vblank)(struct device *subdrv_dev);
 };
@@ -178,7 +181,7 @@ struct exynos_drm_manager {
        int pipe;
        struct exynos_drm_manager_ops *ops;
        struct exynos_drm_overlay_ops *overlay_ops;
-       struct exynos_drm_display *display;
+       struct exynos_drm_display_ops *display_ops;
 };
 
 /*
index 7cf6fa86a67efb57e10407213639e8084d2c2138..153061415bafba2d3c83d155a7e86a4901db0b52 100644 (file)
@@ -53,15 +53,36 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct drm_connector *connector;
        struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+       struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
        DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
 
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               if (manager_ops && manager_ops->commit)
+                       manager_ops->commit(manager->dev);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               /* TODO */
+               if (manager_ops && manager_ops->disable)
+                       manager_ops->disable(manager->dev);
+               break;
+       default:
+               DRM_ERROR("unspecified mode %d\n", mode);
+               break;
+       }
+
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                if (connector->encoder == encoder) {
-                       struct exynos_drm_display *display = manager->display;
+                       struct exynos_drm_display_ops *display_ops =
+                                                       manager->display_ops;
 
-                       if (display && display->power_on)
-                               display->power_on(manager->dev, mode);
+                       DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
+                                       connector->base.id, mode);
+                       if (display_ops && display_ops->power_on)
+                               display_ops->power_on(manager->dev, mode);
                }
        }
 }
@@ -116,15 +137,11 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
        struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
        struct exynos_drm_manager_ops *manager_ops = manager->ops;
-       struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        if (manager_ops && manager_ops->commit)
                manager_ops->commit(manager->dev);
-
-       if (overlay_ops && overlay_ops->commit)
-               overlay_ops->commit(manager->dev);
 }
 
 static struct drm_crtc *
@@ -208,10 +225,23 @@ void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
 {
        struct drm_device *dev = crtc->dev;
        struct drm_encoder *encoder;
+       struct exynos_drm_private *private = dev->dev_private;
+       struct exynos_drm_manager *manager;
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               if (encoder->crtc != crtc)
-                       continue;
+               /*
+                * if crtc is detached from encoder, check pipe,
+                * otherwise check crtc attached to encoder
+                */
+               if (!encoder->crtc) {
+                       manager = to_exynos_encoder(encoder)->manager;
+                       if (manager->pipe < 0 ||
+                                       private->crtc[manager->pipe] != crtc)
+                               continue;
+               } else {
+                       if (encoder->crtc != crtc)
+                               continue;
+               }
 
                fn(encoder, data);
        }
@@ -250,8 +280,18 @@ void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
        struct exynos_drm_manager *manager =
                to_exynos_encoder(encoder)->manager;
        struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+       int crtc = *(int *)data;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       /*
+        * when crtc is detached from encoder, this pipe is used
+        * to select manager operation
+        */
+       manager->pipe = crtc;
 
-       overlay_ops->commit(manager->dev);
+       if (overlay_ops && overlay_ops->commit)
+               overlay_ops->commit(manager->dev);
 }
 
 void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
@@ -261,7 +301,28 @@ void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
        struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
        struct exynos_drm_overlay *overlay = data;
 
-       overlay_ops->mode_set(manager->dev, overlay);
+       if (overlay_ops && overlay_ops->mode_set)
+               overlay_ops->mode_set(manager->dev, overlay);
+}
+
+void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data)
+{
+       struct exynos_drm_manager *manager =
+               to_exynos_encoder(encoder)->manager;
+       struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+
+       DRM_DEBUG_KMS("\n");
+
+       if (overlay_ops && overlay_ops->disable)
+               overlay_ops->disable(manager->dev);
+
+       /*
+        * crtc is already detached from encoder and last
+        * function for detaching is properly done, so
+        * clear pipe from manager to prevent repeated call
+        */
+       if (!encoder->crtc)
+               manager->pipe = -1;
 }
 
 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
index 5ecd645d06a97e1959599ecfd94d2b7ba2d50847..a22acfbf0e4ed6dc31894d03f7a5369158ded8a2 100644 (file)
@@ -41,5 +41,6 @@ void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
 void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
 void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data);
 void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data);
 
 #endif
index 48d29cfd5240197f645c6732a9360bb255656f97..5bf4a1ac7f828cd26509857e5ed9b024f094f831 100644 (file)
@@ -29,7 +29,9 @@
 #include "drmP.h"
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
 
+#include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_buf.h"
 #include "exynos_drm_gem.h"
  *
  * @fb: drm framebuffer obejct.
  * @exynos_gem_obj: exynos specific gem object containing a gem object.
- * @entry: pointer to exynos drm buffer entry object.
- *     - containing only the information to physically continuous memory
- *     region allocated at default framebuffer creation.
+ * @buffer: pointer to exynos_drm_gem_buffer object.
+ *     - contain the memory information to memory region allocated
+ *     at default framebuffer creation.
  */
 struct exynos_drm_fb {
        struct drm_framebuffer          fb;
        struct exynos_drm_gem_obj       *exynos_gem_obj;
-       struct exynos_drm_buf_entry     *entry;
+       struct exynos_drm_gem_buf       *buffer;
 };
 
 static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
@@ -63,8 +65,8 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
         * default framebuffer has no gem object so
         * a buffer of the default framebuffer should be released at here.
         */
-       if (!exynos_fb->exynos_gem_obj && exynos_fb->entry)
-               exynos_drm_buf_destroy(fb->dev, exynos_fb->entry);
+       if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer)
+               exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer);
 
        kfree(exynos_fb);
        exynos_fb = NULL;
@@ -143,29 +145,29 @@ exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
         */
        if (!mode_cmd->handle) {
                if (!file_priv) {
-                       struct exynos_drm_buf_entry *entry;
+                       struct exynos_drm_gem_buf *buffer;
 
                        /*
                         * in case that file_priv is NULL, it allocates
                         * only buffer and this buffer would be used
                         * for default framebuffer.
                         */
-                       entry = exynos_drm_buf_create(dev, size);
-                       if (IS_ERR(entry)) {
-                               ret = PTR_ERR(entry);
+                       buffer = exynos_drm_buf_create(dev, size);
+                       if (IS_ERR(buffer)) {
+                               ret = PTR_ERR(buffer);
                                goto err_buffer;
                        }
 
-                       exynos_fb->entry = entry;
+                       exynos_fb->buffer = buffer;
 
-                       DRM_LOG_KMS("default fb: paddr = 0x%lx, size = 0x%x\n",
-                                       (unsigned long)entry->paddr, size);
+                       DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n",
+                                       (unsigned long)buffer->dma_addr, size);
 
                        goto out;
                } else {
-                       exynos_gem_obj = exynos_drm_gem_create(file_priv, dev,
-                                                       size,
-                                                       &mode_cmd->handle);
+                       exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
+                                                       &mode_cmd->handle,
+                                                       size);
                        if (IS_ERR(exynos_gem_obj)) {
                                ret = PTR_ERR(exynos_gem_obj);
                                goto err_buffer;
@@ -189,10 +191,10 @@ exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
         * so that default framebuffer has no its own gem object,
         * only its own buffer object.
         */
-       exynos_fb->entry = exynos_gem_obj->entry;
+       exynos_fb->buffer = exynos_gem_obj->buffer;
 
-       DRM_LOG_KMS("paddr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
-                       (unsigned long)exynos_fb->entry->paddr, size,
+       DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
+                       (unsigned long)exynos_fb->buffer->dma_addr, size,
                        (unsigned int)&exynos_gem_obj->base);
 
 out:
@@ -220,26 +222,36 @@ struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
        return exynos_drm_fb_init(file_priv, dev, mode_cmd);
 }
 
-struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
+struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
 {
        struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       entry = exynos_fb->entry;
-       if (!entry)
+       buffer = exynos_fb->buffer;
+       if (!buffer)
                return NULL;
 
-       DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
-                       (unsigned long)entry->vaddr,
-                       (unsigned long)entry->paddr);
+       DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
+                       (unsigned long)buffer->kvaddr,
+                       (unsigned long)buffer->dma_addr);
 
-       return entry;
+       return buffer;
+}
+
+static void exynos_drm_output_poll_changed(struct drm_device *dev)
+{
+       struct exynos_drm_private *private = dev->dev_private;
+       struct drm_fb_helper *fb_helper = private->fb_helper;
+
+       if (fb_helper)
+               drm_fb_helper_hotplug_event(fb_helper);
 }
 
 static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
        .fb_create = exynos_drm_fb_create,
+       .output_poll_changed = exynos_drm_output_poll_changed,
 };
 
 void exynos_drm_mode_config_init(struct drm_device *dev)
index 1f4b3d1a77134d46ae193446a2720020dfd745cf..836f4100818710e830229b985591bfc85a047f03 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
 #include "exynos_drm_buf.h"
 
 #define MAX_CONNECTOR          4
@@ -85,15 +86,13 @@ static struct fb_ops exynos_drm_fb_ops = {
 };
 
 static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
-                                    struct drm_framebuffer *fb,
-                                    unsigned int fb_width,
-                                    unsigned int fb_height)
+                                    struct drm_framebuffer *fb)
 {
        struct fb_info *fbi = helper->fbdev;
        struct drm_device *dev = helper->dev;
        struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
-       struct exynos_drm_buf_entry *entry;
-       unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3);
+       struct exynos_drm_gem_buf *buffer;
+       unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
        unsigned long offset;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -101,20 +100,20 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
        exynos_fb->fb = fb;
 
        drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
-       drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height);
+       drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
 
-       entry = exynos_drm_fb_get_buf(fb);
-       if (!entry) {
-               DRM_LOG_KMS("entry is null.\n");
+       buffer = exynos_drm_fb_get_buf(fb);
+       if (!buffer) {
+               DRM_LOG_KMS("buffer is null.\n");
                return -EFAULT;
        }
 
        offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
        offset += fbi->var.yoffset * fb->pitch;
 
-       dev->mode_config.fb_base = entry->paddr;
-       fbi->screen_base = entry->vaddr + offset;
-       fbi->fix.smem_start = entry->paddr + offset;
+       dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
+       fbi->screen_base = buffer->kvaddr + offset;
+       fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
        fbi->screen_size = size;
        fbi->fix.smem_len = size;
 
@@ -171,8 +170,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
                goto out;
        }
 
-       ret = exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
-                       sizes->fb_height);
+       ret = exynos_drm_fbdev_update(helper, helper->fb);
        if (ret < 0)
                fb_dealloc_cmap(&fbi->cmap);
 
@@ -235,8 +233,7 @@ static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
        }
 
        helper->fb = exynos_fbdev->fb;
-       return exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
-                       sizes->fb_height);
+       return exynos_drm_fbdev_update(helper, helper->fb);
 }
 
 static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
@@ -405,6 +402,18 @@ int exynos_drm_fbdev_reinit(struct drm_device *dev)
        fb_helper = private->fb_helper;
 
        if (fb_helper) {
+               struct list_head temp_list;
+
+               INIT_LIST_HEAD(&temp_list);
+
+               /*
+                * fb_helper is reintialized but kernel fb is reused
+                * so kernel_fb_list need to be backuped and restored
+                */
+               if (!list_empty(&fb_helper->kernel_fb_list))
+                       list_replace_init(&fb_helper->kernel_fb_list,
+                                       &temp_list);
+
                drm_fb_helper_fini(fb_helper);
 
                ret = drm_fb_helper_init(dev, fb_helper,
@@ -414,6 +423,9 @@ int exynos_drm_fbdev_reinit(struct drm_device *dev)
                        return ret;
                }
 
+               if (!list_empty(&temp_list))
+                       list_replace(&temp_list, &fb_helper->kernel_fb_list);
+
                ret = drm_fb_helper_single_add_all_connectors(fb_helper);
                if (ret < 0) {
                        DRM_ERROR("failed to add fb helper to connectors\n");
index 4659c88cdd9bbaec81e6d6d1d9fe1d7b03964dec..db3b3d9e731d86475d734884e2ec113a8be5f914 100644 (file)
@@ -64,7 +64,7 @@ struct fimd_win_data {
        unsigned int            fb_width;
        unsigned int            fb_height;
        unsigned int            bpp;
-       dma_addr_t              paddr;
+       dma_addr_t              dma_addr;
        void __iomem            *vaddr;
        unsigned int            buf_offsize;
        unsigned int            line_size;      /* bytes */
@@ -124,7 +124,7 @@ static int fimd_display_power_on(struct device *dev, int mode)
        return 0;
 }
 
-static struct exynos_drm_display fimd_display = {
+static struct exynos_drm_display_ops fimd_display_ops = {
        .type = EXYNOS_DISPLAY_TYPE_LCD,
        .is_connected = fimd_display_is_connected,
        .get_timing = fimd_get_timing,
@@ -177,6 +177,40 @@ static void fimd_commit(struct device *dev)
        writel(val, ctx->regs + VIDCON0);
 }
 
+static void fimd_disable(struct device *dev)
+{
+       struct fimd_context *ctx = get_fimd_context(dev);
+       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+       struct drm_device *drm_dev = subdrv->drm_dev;
+       struct exynos_drm_manager *manager = &subdrv->manager;
+       u32 val;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       /* fimd dma off */
+       val = readl(ctx->regs + VIDCON0);
+       val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
+       writel(val, ctx->regs + VIDCON0);
+
+       /*
+        * if vblank is enabled status with dma off then
+        * it disables vsync interrupt.
+        */
+       if (drm_dev->vblank_enabled[manager->pipe] &&
+               atomic_read(&drm_dev->vblank_refcount[manager->pipe])) {
+               drm_vblank_put(drm_dev, manager->pipe);
+
+               /*
+                * if vblank_disable_allowed is 0 then disable
+                * vsync interrupt right now else the vsync interrupt
+                * would be disabled by drm timer once a current process
+                * gives up ownershop of vblank event.
+                */
+               if (!drm_dev->vblank_disable_allowed)
+                       drm_vblank_off(drm_dev, manager->pipe);
+       }
+}
+
 static int fimd_enable_vblank(struct device *dev)
 {
        struct fimd_context *ctx = get_fimd_context(dev);
@@ -220,6 +254,7 @@ static void fimd_disable_vblank(struct device *dev)
 
 static struct exynos_drm_manager_ops fimd_manager_ops = {
        .commit = fimd_commit,
+       .disable = fimd_disable,
        .enable_vblank = fimd_enable_vblank,
        .disable_vblank = fimd_disable_vblank,
 };
@@ -251,7 +286,7 @@ static void fimd_win_mode_set(struct device *dev,
        win_data->ovl_height = overlay->crtc_height;
        win_data->fb_width = overlay->fb_width;
        win_data->fb_height = overlay->fb_height;
-       win_data->paddr = overlay->paddr + offset;
+       win_data->dma_addr = overlay->dma_addr + offset;
        win_data->vaddr = overlay->vaddr + offset;
        win_data->bpp = overlay->bpp;
        win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
@@ -263,7 +298,7 @@ static void fimd_win_mode_set(struct device *dev,
        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
                        win_data->ovl_width, win_data->ovl_height);
        DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
-                       (unsigned long)win_data->paddr,
+                       (unsigned long)win_data->dma_addr,
                        (unsigned long)win_data->vaddr);
        DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
                        overlay->fb_width, overlay->crtc_width);
@@ -376,16 +411,16 @@ static void fimd_win_commit(struct device *dev)
        writel(val, ctx->regs + SHADOWCON);
 
        /* buffer start address */
-       val = win_data->paddr;
+       val = (unsigned long)win_data->dma_addr;
        writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 
        /* buffer end address */
        size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
-       val = win_data->paddr + size;
+       val = (unsigned long)(win_data->dma_addr + size);
        writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
 
        DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
-                       (unsigned long)win_data->paddr, val, size);
+                       (unsigned long)win_data->dma_addr, val, size);
        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
                        win_data->ovl_width, win_data->ovl_height);
 
@@ -447,7 +482,6 @@ static void fimd_win_commit(struct device *dev)
 static void fimd_win_disable(struct device *dev)
 {
        struct fimd_context *ctx = get_fimd_context(dev);
-       struct fimd_win_data *win_data;
        int win = ctx->default_win;
        u32 val;
 
@@ -456,8 +490,6 @@ static void fimd_win_disable(struct device *dev)
        if (win < 0 || win > WINDOWS_NR)
                return;
 
-       win_data = &ctx->win_data[win];
-
        /* protect windows */
        val = readl(ctx->regs + SHADOWCON);
        val |= SHADOWCON_WINx_PROTECT(win);
@@ -528,6 +560,16 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
                /* VSYNC interrupt */
                writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
 
+       /*
+        * in case that vblank_disable_allowed is 1, it could induce
+        * the problem that manager->pipe could be -1 because with
+        * disable callback, vsync interrupt isn't disabled and at this moment,
+        * vsync interrupt could occur. the vsync interrupt would be disabled
+        * by timer handler later.
+        */
+       if (manager->pipe == -1)
+               return IRQ_HANDLED;
+
        drm_handle_vblank(drm_dev, manager->pipe);
        fimd_finish_pageflip(drm_dev, manager->pipe);
 
@@ -548,13 +590,6 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
         */
        drm_dev->irq_enabled = 1;
 
-       /*
-        * with vblank_disable_allowed = 1, vblank interrupt will be disabled
-        * by drm timer once a current process gives up ownership of
-        * vblank event.(drm_vblank_put function was called)
-        */
-       drm_dev->vblank_disable_allowed = 1;
-
        return 0;
 }
 
@@ -731,7 +766,7 @@ static int __devinit fimd_probe(struct platform_device *pdev)
        subdrv->manager.pipe = -1;
        subdrv->manager.ops = &fimd_manager_ops;
        subdrv->manager.overlay_ops = &fimd_overlay_ops;
-       subdrv->manager.display = &fimd_display;
+       subdrv->manager.display_ops = &fimd_display_ops;
        subdrv->manager.dev = dev;
 
        platform_set_drvdata(pdev, ctx);
index a8e7a88906ed22e43fb23d23a859dc825a335451..aba0fe47f7eaae47c10ac4b0839eba8c1edf7f54 100644 (file)
@@ -62,40 +62,28 @@ static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
        return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
 }
 
-struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv,
-               struct drm_device *dev, unsigned int size,
-               unsigned int *handle)
+static struct exynos_drm_gem_obj
+               *exynos_drm_gem_init(struct drm_device *drm_dev,
+                       struct drm_file *file_priv, unsigned int *handle,
+                       unsigned int size)
 {
        struct exynos_drm_gem_obj *exynos_gem_obj;
-       struct exynos_drm_buf_entry *entry;
        struct drm_gem_object *obj;
        int ret;
 
-       DRM_DEBUG_KMS("%s\n", __FILE__);
-
-       size = roundup(size, PAGE_SIZE);
-
        exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
        if (!exynos_gem_obj) {
                DRM_ERROR("failed to allocate exynos gem object.\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       /* allocate the new buffer object and memory region. */
-       entry = exynos_drm_buf_create(dev, size);
-       if (!entry) {
-               kfree(exynos_gem_obj);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       exynos_gem_obj->entry = entry;
-
        obj = &exynos_gem_obj->base;
 
-       ret = drm_gem_object_init(dev, obj, size);
+       ret = drm_gem_object_init(drm_dev, obj, size);
        if (ret < 0) {
-               DRM_ERROR("failed to initailize gem object.\n");
-               goto err_obj_init;
+               DRM_ERROR("failed to initialize gem object.\n");
+               ret = -EINVAL;
+               goto err_object_init;
        }
 
        DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
@@ -127,24 +115,50 @@ err_handle_create:
 err_create_mmap_offset:
        drm_gem_object_release(obj);
 
-err_obj_init:
-       exynos_drm_buf_destroy(dev, exynos_gem_obj->entry);
-
+err_object_init:
        kfree(exynos_gem_obj);
 
        return ERR_PTR(ret);
 }
 
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
+                               struct drm_file *file_priv,
+                               unsigned int *handle, unsigned long size)
+{
+
+       struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+       struct exynos_drm_gem_buf *buffer;
+
+       size = roundup(size, PAGE_SIZE);
+
+       DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
+
+       buffer = exynos_drm_buf_create(dev, size);
+       if (IS_ERR(buffer)) {
+               return ERR_CAST(buffer);
+       }
+
+       exynos_gem_obj = exynos_drm_gem_init(dev, file_priv, handle, size);
+       if (IS_ERR(exynos_gem_obj)) {
+               exynos_drm_buf_destroy(dev, buffer);
+               return exynos_gem_obj;
+       }
+
+       exynos_gem_obj->buffer = buffer;
+
+       return exynos_gem_obj;
+}
+
 int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
-               struct drm_file *file_priv)
+                                       struct drm_file *file_priv)
 {
        struct drm_exynos_gem_create *args = data;
-       struct exynos_drm_gem_obj *exynos_gem_obj;
+       struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
 
-       DRM_DEBUG_KMS("%s : size = 0x%x\n", __FILE__, args->size);
+       DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size,
-                       &args->handle);
+       exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
+                                               &args->handle, args->size);
        if (IS_ERR(exynos_gem_obj))
                return PTR_ERR(exynos_gem_obj);
 
@@ -175,7 +189,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
 {
        struct drm_gem_object *obj = filp->private_data;
        struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
        unsigned long pfn, vm_size;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -187,20 +201,20 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
 
        vm_size = vma->vm_end - vma->vm_start;
        /*
-        * a entry contains information to physically continuous memory
+        * a buffer contains information to physically continuous memory
         * allocated by user request or at framebuffer creation.
         */
-       entry = exynos_gem_obj->entry;
+       buffer = exynos_gem_obj->buffer;
 
        /* check if user-requested size is valid. */
-       if (vm_size > entry->size)
+       if (vm_size > buffer->size)
                return -EINVAL;
 
        /*
         * get page frame number to physical memory to be mapped
         * to user space.
         */
-       pfn = exynos_gem_obj->entry->paddr >> PAGE_SHIFT;
+       pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >> PAGE_SHIFT;
 
        DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn);
 
@@ -281,7 +295,7 @@ void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj)
 
        exynos_gem_obj = to_exynos_gem_obj(gem_obj);
 
-       exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->entry);
+       exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->buffer);
 
        kfree(exynos_gem_obj);
 }
@@ -302,8 +316,8 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
        args->pitch = args->width * args->bpp >> 3;
        args->size = args->pitch * args->height;
 
-       exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size,
-                                                       &args->handle);
+       exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, &args->handle,
+                                                       args->size);
        if (IS_ERR(exynos_gem_obj))
                return PTR_ERR(exynos_gem_obj);
 
@@ -360,7 +374,8 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        mutex_lock(&dev->struct_mutex);
 
-       pfn = (exynos_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset;
+       pfn = (((unsigned long)exynos_gem_obj->buffer->dma_addr) >>
+                       PAGE_SHIFT) + page_offset;
 
        ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
 
index e5fc0148277bf84b5fe8c9a31365256c940da802..ef8797334e6da746c54eed761521aacdc7afd7a8 100644 (file)
 #define to_exynos_gem_obj(x)   container_of(x,\
                        struct exynos_drm_gem_obj, base)
 
+/*
+ * exynos drm gem buffer structure.
+ *
+ * @kvaddr: kernel virtual address to allocated memory region.
+ * @dma_addr: bus address(accessed by dma) to allocated memory region.
+ *     - this address could be physical address without IOMMU and
+ *     device address with IOMMU.
+ * @size: size of allocated memory region.
+ */
+struct exynos_drm_gem_buf {
+       void __iomem            *kvaddr;
+       dma_addr_t              dma_addr;
+       unsigned long           size;
+};
+
 /*
  * exynos drm buffer structure.
  *
  * @base: a gem object.
  *     - a new handle to this gem object would be created
  *     by drm_gem_handle_create().
- * @entry: pointer to exynos drm buffer entry object.
- *     - containing the information to physically
+ * @buffer: a pointer to exynos_drm_gem_buffer object.
+ *     - contain the information to memory region allocated
+ *     by user request or at framebuffer creation.
  *     continuous memory region allocated by user request
  *     or at framebuffer creation.
  *
  */
 struct exynos_drm_gem_obj {
        struct drm_gem_object base;
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
 };
 
 /* create a new buffer and get a new gem handle. */
-struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv,
-               struct drm_device *dev, unsigned int size,
-               unsigned int *handle);
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
+               struct drm_file *file_priv,
+               unsigned int *handle, unsigned long size);
 
 /*
  * request gem object creation and buffer allocation as the size
index d14b44e13f5190e73077a70c48508010fb311602..d09a6e02dc95374caf456923cba25efa94aafa94 100644 (file)
@@ -636,11 +636,16 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring;
+       int ret;
 
        ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
        if (ring->size == 0)
                return 0;
 
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
        seq_printf(m, "Ring %s:\n", ring->name);
        seq_printf(m, "  Head :    %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR);
        seq_printf(m, "  Tail :    %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR);
@@ -654,6 +659,8 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
        seq_printf(m, "  Control : %08x\n", I915_READ_CTL(ring));
        seq_printf(m, "  Start :   %08x\n", I915_READ_START(ring));
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -842,7 +849,16 @@ static int i915_rstdby_delays(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;
-       u16 crstanddelay = I915_READ16(CRSTANDVID);
+       u16 crstanddelay;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       crstanddelay = I915_READ16(CRSTANDVID);
+
+       mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
 
@@ -940,7 +956,11 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 delayfreq;
-       int i;
+       int ret, i;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
 
        for (i = 0; i < 16; i++) {
                delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -948,6 +968,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
                           (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
        }
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -962,13 +984,19 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 inttoext;
-       int i;
+       int ret, i;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
 
        for (i = 1; i <= 32; i++) {
                inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
                seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
        }
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -977,9 +1005,19 @@ static int i915_drpc_info(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;
-       u32 rgvmodectl = I915_READ(MEMMODECTL);
-       u32 rstdbyctl = I915_READ(RSTDBYCTL);
-       u16 crstandvid = I915_READ16(CRSTANDVID);
+       u32 rgvmodectl, rstdbyctl;
+       u16 crstandvid;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       rgvmodectl = I915_READ(MEMMODECTL);
+       rstdbyctl = I915_READ(RSTDBYCTL);
+       crstandvid = I915_READ16(CRSTANDVID);
+
+       mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
                   "yes" : "no");
@@ -1167,9 +1205,16 @@ static int i915_gfxec(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;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
 
        seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -1506,7 +1551,10 @@ drm_add_fake_info_node(struct drm_minor *minor,
        node->minor = minor;
        node->dent = ent;
        node->info_ent = (void *) key;
-       list_add(&node->list, &minor->debugfs_nodes.list);
+
+       mutex_lock(&minor->debugfs_lock);
+       list_add(&node->list, &minor->debugfs_list);
+       mutex_unlock(&minor->debugfs_lock);
 
        return 0;
 }
index cc531bb59c26f7ccc8b7de8721f1b94bce576be6..15bfa9145d2b7f007b21f54ecee19b8b502648f2 100644 (file)
@@ -68,7 +68,7 @@ module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
 MODULE_PARM_DESC(i915_enable_rc6,
                "Enable power-saving render C-state 6 (default: true)");
 
-unsigned int i915_enable_fbc __read_mostly = -1;
+int i915_enable_fbc __read_mostly = -1;
 module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
 MODULE_PARM_DESC(i915_enable_fbc,
                "Enable frame buffer compression for power savings "
@@ -80,7 +80,7 @@ MODULE_PARM_DESC(lvds_downclock,
                "Use panel (LVDS/eDP) downclocking for power savings "
                "(default: false)");
 
-unsigned int i915_panel_use_ssc __read_mostly = -1;
+int i915_panel_use_ssc __read_mostly = -1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
 MODULE_PARM_DESC(lvds_use_ssc,
                "Use Spread Spectrum Clock with panels [LVDS/eDP] "
@@ -107,7 +107,7 @@ static struct drm_driver driver;
 extern int intel_agp_enabled;
 
 #define INTEL_VGA_DEVICE(id, info) {           \
-       .class = PCI_CLASS_DISPLAY_VGA << 8,    \
+       .class = PCI_BASE_CLASS_DISPLAY << 16,  \
        .class_mask = 0xff0000,                 \
        .vendor = 0x8086,                       \
        .device = id,                           \
@@ -789,8 +789,8 @@ static struct vm_operations_struct i915_gem_vm_ops = {
 };
 
 static struct drm_driver driver = {
-       /* don't use mtrr's here, the Xserver or user space app should
-        * deal with them for intel hardware.
+       /* Don't use MTRRs here; the Xserver or userspace app should
+        * deal with them for Intel hardware.
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
index 06a37f4fd74b17ad82a0ba912da22d9df63e0dba..4a9c1b97980493b47c1f4e03a7e299f800a7f4e0 100644 (file)
@@ -126,6 +126,9 @@ struct drm_i915_master_private {
        struct _drm_i915_sarea *sarea_priv;
 };
 #define I915_FENCE_REG_NONE -1
+#define I915_MAX_NUM_FENCES 16
+/* 16 fences + sign bit for FENCE_REG_NONE */
+#define I915_MAX_NUM_FENCE_BITS 5
 
 struct drm_i915_fence_reg {
        struct list_head lru_list;
@@ -168,7 +171,7 @@ struct drm_i915_error_state {
        u32 instdone1;
        u32 seqno;
        u64 bbaddr;
-       u64 fence[16];
+       u64 fence[I915_MAX_NUM_FENCES];
        struct timeval time;
        struct drm_i915_error_object {
                int page_count;
@@ -182,7 +185,7 @@ struct drm_i915_error_state {
                u32 gtt_offset;
                u32 read_domains;
                u32 write_domain;
-               s32 fence_reg:5;
+               s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
                s32 pinned:2;
                u32 tiling:2;
                u32 dirty:1;
@@ -375,7 +378,7 @@ typedef struct drm_i915_private {
        struct notifier_block lid_notifier;
 
        int crt_ddc_pin;
-       struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
+       struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* 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 */
 
@@ -506,7 +509,7 @@ typedef struct drm_i915_private {
        u8 saveAR[21];
        u8 saveDACMASK;
        u8 saveCR[37];
-       uint64_t saveFENCE[16];
+       uint64_t saveFENCE[I915_MAX_NUM_FENCES];
        u32 saveCURACNTR;
        u32 saveCURAPOS;
        u32 saveCURABASE;
@@ -777,10 +780,8 @@ struct drm_i915_gem_object {
         * Fence register bits (if any) for this object.  Will be set
         * as needed when mapped into the GTT.
         * Protected by dev->struct_mutex.
-        *
-        * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
         */
-       signed int fence_reg:5;
+       signed int fence_reg:I915_MAX_NUM_FENCE_BITS;
 
        /**
         * Advice: are the backing pages purgeable?
@@ -999,10 +1000,10 @@ extern int i915_panel_ignore_lid __read_mostly;
 extern unsigned int i915_powersave __read_mostly;
 extern unsigned int i915_semaphores __read_mostly;
 extern unsigned int i915_lvds_downclock __read_mostly;
-extern unsigned int i915_panel_use_ssc __read_mostly;
+extern int i915_panel_use_ssc __read_mostly;
 extern int i915_vbt_sdvo_panel_type __read_mostly;
 extern unsigned int i915_enable_rc6 __read_mostly;
-extern unsigned int i915_enable_fbc __read_mostly;
+extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
index 6651c36b6e8a16a59231fafb83d24709732a7b7f..8359dc777041be9265e53907025564196b1d0fbc 100644 (file)
@@ -1396,7 +1396,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
 
        if (obj->base.size > dev_priv->mm.gtt_mappable_end) {
                ret = -E2BIG;
-               goto unlock;
+               goto out;
        }
 
        if (obj->madv != I915_MADV_WILLNEED) {
@@ -1745,7 +1745,7 @@ static void i915_gem_reset_fences(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int i;
 
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < dev_priv->num_fence_regs; i++) {
                struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
                struct drm_i915_gem_object *obj = reg->obj;
 
@@ -3512,9 +3512,11 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
                         * so emit a request to do so.
                         */
                        request = kzalloc(sizeof(*request), GFP_KERNEL);
-                       if (request)
+                       if (request) {
                                ret = i915_add_request(obj->ring, NULL, request);
-                       else
+                               if (ret)
+                                       kfree(request);
+                       } else
                                ret = -ENOMEM;
                }
 
@@ -3613,7 +3615,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
        obj->base.write_domain = I915_GEM_DOMAIN_CPU;
        obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 
-       if (IS_GEN6(dev)) {
+       if (IS_GEN6(dev) || IS_GEN7(dev)) {
                /* On Gen6, we can have the GPU use the LLC (the CPU
                 * cache) for about a 10% performance improvement
                 * compared to uncached.  Graphics requests other than
@@ -3877,7 +3879,7 @@ i915_gem_load(struct drm_device *dev)
        INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
        for (i = 0; i < I915_NUM_RINGS; i++)
                init_ring_lists(&dev_priv->ring[i]);
-       for (i = 0; i < 16; i++)
+       for (i = 0; i < I915_MAX_NUM_FENCES; i++)
                INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
        INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
                          i915_gem_retire_work_handler);
index 9ee2729fe5c65ec3690a1f9dcf403045c79a4907..b40004b559771dc0244814335d44fb1537625087 100644 (file)
@@ -824,6 +824,7 @@ static void i915_gem_record_fences(struct drm_device *dev,
 
        /* Fences */
        switch (INTEL_INFO(dev)->gen) {
+       case 7:
        case 6:
                for (i = 0; i < 16; i++)
                        error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
index 5a09416e611f566774e18ad7095d3c007ea1876b..b080cc82400153a68aed7cca1f3319de361a1f93 100644 (file)
  */
 #define   PP_READY             (1 << 30)
 #define   PP_SEQUENCE_NONE     (0 << 28)
-#define   PP_SEQUENCE_ON       (1 << 28)
-#define   PP_SEQUENCE_OFF      (2 << 28)
-#define   PP_SEQUENCE_MASK     0x30000000
+#define   PP_SEQUENCE_POWER_UP (1 << 28)
+#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
+#define   PP_SEQUENCE_MASK     (3 << 28)
+#define   PP_SEQUENCE_SHIFT    28
 #define   PP_CYCLE_DELAY_ACTIVE        (1 << 27)
-#define   PP_SEQUENCE_STATE_ON_IDLE (1 << 3)
 #define   PP_SEQUENCE_STATE_MASK 0x0000000f
+#define   PP_SEQUENCE_STATE_OFF_IDLE   (0x0 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_1   (0x1 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_2   (0x2 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_3   (0x3 << 0)
+#define   PP_SEQUENCE_STATE_ON_IDLE    (0x8 << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_0    (0x9 << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_2    (0xa << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_3    (0xb << 0)
+#define   PP_SEQUENCE_STATE_RESET      (0xf << 0)
 #define PP_CONTROL     0x61204
 #define   POWER_TARGET_ON      (1 << 0)
 #define PP_ON_DELAYS   0x61208
 #define  GT_FIFO_FREE_ENTRIES                  0x120008
 #define    GT_FIFO_NUM_RESERVED_ENTRIES                20
 
+#define GEN6_UCGCTL2                           0x9404
+# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE              (1 << 12)
+# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE               (1 << 11)
+
 #define GEN6_RPNSWREQ                          0xA008
 #define   GEN6_TURBO_DISABLE                   (1<<31)
 #define   GEN6_FREQUENCY(x)                    ((x)<<25)
index f8f602d76650177c1d7b3a11c9cac3b185fee1bf..7886e4fb60e3e23fb283461a690dbe43a928fc6e 100644 (file)
@@ -370,6 +370,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
 
        /* Fences */
        switch (INTEL_INFO(dev)->gen) {
+       case 7:
        case 6:
                for (i = 0; i < 16; i++)
                        dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
@@ -404,6 +405,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
 
        /* Fences */
        switch (INTEL_INFO(dev)->gen) {
+       case 7:
        case 6:
                for (i = 0; i < 16; i++)
                        I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
index 981b1f1c04d8da4459f9ae776cf0681576eb915f..e77a863a3833f63511a98991508b2f5c1a6ee0d1 100644 (file)
@@ -2933,7 +2933,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 
        /* For PCH DP, enable TRANS_DP_CTL */
        if (HAS_PCH_CPT(dev) &&
-           intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+           (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+            intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
                u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
                reg = TRANS_DP_CTL(pipe);
                temp = I915_READ(reg);
@@ -4711,7 +4712,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                                lvds_bpc = 6;
 
                        if (lvds_bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
                                display_bpc = lvds_bpc;
                        }
                        continue;
@@ -4722,7 +4723,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        unsigned int edp_bpc = dev_priv->edp.bpp / 3;
 
                        if (edp_bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
                                display_bpc = edp_bpc;
                        }
                        continue;
@@ -4737,7 +4738,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        /* Don't use an invalid EDID bpc value */
                        if (connector->display_info.bpc &&
                            connector->display_info.bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
                                display_bpc = connector->display_info.bpc;
                        }
                }
@@ -4748,10 +4749,10 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                 */
                if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
                        if (display_bpc > 8 && display_bpc < 12) {
-                               DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
+                               DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
                                display_bpc = 12;
                        } else {
-                               DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
+                               DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
                                display_bpc = 8;
                        }
                }
@@ -4789,8 +4790,8 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
 
        display_bpc = min(display_bpc, bpc);
 
-       DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
-                        bpc, display_bpc);
+       DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
+                     bpc, display_bpc);
 
        *pipe_bpp = display_bpc * 3;
 
@@ -5671,7 +5672,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
        if ((is_lvds && dev_priv->lvds_dither) || dither) {
                pipeconf |= PIPECONF_DITHER_EN;
-               pipeconf |= PIPECONF_DITHER_TYPE_ST1;
+               pipeconf |= PIPECONF_DITHER_TYPE_SP;
        }
        if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
                intel_dp_set_m_n(crtc, mode, adjusted_mode);
@@ -8148,6 +8149,20 @@ static void gen6_init_clock_gating(struct drm_device *dev)
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
 
+       /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+        * gating disable must be set.  Failure to set it results in
+        * flickering pixels due to Z write ordering failures after
+        * some amount of runtime in the Mesa "fire" demo, and Unigine
+        * Sanctuary and Tropics, and apparently anything else with
+        * alpha test or pixel discard.
+        *
+        * According to the spec, bit 11 (RCCUNIT) must also be set,
+        * but we didn't debug actual testcases to find it out.
+        */
+       I915_WRITE(GEN6_UCGCTL2,
+                  GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+
        /*
         * According to the spec the following bits should be
         * set in order to enable memory self-refresh and fbc:
index 09b318b0227f3571402c479c06bb376c6aae7eda..4d0358fad93795c31dd9d4229daa3c7c2ecedcc5 100644 (file)
@@ -59,7 +59,6 @@ struct intel_dp {
        struct i2c_algo_dp_aux_data algo;
        bool is_pch_edp;
        uint8_t train_set[4];
-       uint8_t link_status[DP_LINK_STATUS_SIZE];
        int panel_power_up_delay;
        int panel_power_down_delay;
        int panel_power_cycle_delay;
@@ -68,7 +67,6 @@ struct intel_dp {
        struct drm_display_mode *panel_fixed_mode;  /* for eDP */
        struct delayed_work panel_vdd_work;
        bool want_panel_vdd;
-       unsigned long panel_off_jiffies;
 };
 
 /**
@@ -157,16 +155,12 @@ intel_edp_link_config(struct intel_encoder *intel_encoder,
 static int
 intel_dp_max_lane_count(struct intel_dp *intel_dp)
 {
-       int max_lane_count = 4;
-
-       if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
-               max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
-               switch (max_lane_count) {
-               case 1: case 2: case 4:
-                       break;
-               default:
-                       max_lane_count = 4;
-               }
+       int max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
+       switch (max_lane_count) {
+       case 1: case 2: case 4:
+               break;
+       default:
+               max_lane_count = 4;
        }
        return max_lane_count;
 }
@@ -768,12 +762,11 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                        continue;
 
                intel_dp = enc_to_intel_dp(encoder);
-               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) {
+               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
+                   intel_dp->base.type == INTEL_OUTPUT_EDP)
+               {
                        lane_count = intel_dp->lane_count;
                        break;
-               } else if (is_edp(intel_dp)) {
-                       lane_count = dev_priv->edp.lanes;
-                       break;
                }
        }
 
@@ -810,6 +803,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                  struct drm_display_mode *adjusted_mode)
 {
        struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        struct drm_crtc *crtc = intel_dp->base.base.crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -822,18 +816,31 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                        ironlake_edp_pll_off(encoder);
        }
 
-       intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
-       intel_dp->DP |= intel_dp->color_range;
+       /*
+        * There are three kinds of DP registers:
+        *
+        *      IBX PCH
+        *      CPU
+        *      CPT PCH
+        *
+        * IBX PCH and CPU are the same for almost everything,
+        * except that the CPU DP PLL is configured in this
+        * register
+        *
+        * CPT PCH is quite different, having many bits moved
+        * to the TRANS_DP_CTL register instead. That
+        * configuration happens (oddly) in ironlake_pch_enable
+        */
 
-       if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-               intel_dp->DP |= DP_SYNC_HS_HIGH;
-       if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-               intel_dp->DP |= DP_SYNC_VS_HIGH;
+       /* Preserve the BIOS-computed detected bit. This is
+        * supposed to be read-only.
+        */
+       intel_dp->DP = I915_READ(intel_dp->output_reg) & DP_DETECTED;
+       intel_dp->DP |=  DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
-       if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
-               intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
-       else
-               intel_dp->DP |= DP_LINK_TRAIN_OFF;
+       /* Handle DP bits in common between all three register formats */
+
+       intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
        switch (intel_dp->lane_count) {
        case 1:
@@ -852,59 +859,106 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
                intel_write_eld(encoder, adjusted_mode);
        }
-
        memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
        intel_dp->link_configuration[0] = intel_dp->link_bw;
        intel_dp->link_configuration[1] = intel_dp->lane_count;
        intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
-
        /*
         * Check for DPCD version > 1.1 and enhanced framing support
         */
        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
            (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
                intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-               intel_dp->DP |= DP_ENHANCED_FRAMING;
        }
 
-       /* CPT DP's pipe select is decided in TRANS_DP_CTL */
-       if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
-               intel_dp->DP |= DP_PIPEB_SELECT;
+       /* Split out the IBX/CPU vs CPT settings */
 
-       if (is_cpu_edp(intel_dp)) {
-               /* don't miss out required setting for eDP */
-               intel_dp->DP |= DP_PLL_ENABLE;
-               if (adjusted_mode->clock < 200000)
-                       intel_dp->DP |= DP_PLL_FREQ_160MHZ;
-               else
-                       intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+       if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
+               intel_dp->DP |= intel_dp->color_range;
+
+               if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+                       intel_dp->DP |= DP_SYNC_HS_HIGH;
+               if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+                       intel_dp->DP |= DP_SYNC_VS_HIGH;
+               intel_dp->DP |= DP_LINK_TRAIN_OFF;
+
+               if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+                       intel_dp->DP |= DP_ENHANCED_FRAMING;
+
+               if (intel_crtc->pipe == 1)
+                       intel_dp->DP |= DP_PIPEB_SELECT;
+
+               if (is_cpu_edp(intel_dp)) {
+                       /* don't miss out required setting for eDP */
+                       intel_dp->DP |= DP_PLL_ENABLE;
+                       if (adjusted_mode->clock < 200000)
+                               intel_dp->DP |= DP_PLL_FREQ_160MHZ;
+                       else
+                               intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+               }
+       } else {
+               intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
        }
 }
 
-static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
+#define IDLE_ON_MASK           (PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_ON_VALUE          (PP_ON | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
+
+#define IDLE_OFF_MASK          (PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_OFF_VALUE         (0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+#define IDLE_CYCLE_MASK                (PP_ON | 0        | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
+#define IDLE_CYCLE_VALUE       (0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
+                                      u32 mask,
+                                      u32 value)
 {
-       unsigned long   off_time;
-       unsigned long   delay;
+       struct drm_device *dev = intel_dp->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
-       DRM_DEBUG_KMS("Wait for panel power off time\n");
+       DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
+                     mask, value,
+                     I915_READ(PCH_PP_STATUS),
+                     I915_READ(PCH_PP_CONTROL));
 
-       if (ironlake_edp_have_panel_power(intel_dp) ||
-           ironlake_edp_have_panel_vdd(intel_dp))
-       {
-               DRM_DEBUG_KMS("Panel still on, no delay needed\n");
-               return;
+       if (_wait_for((I915_READ(PCH_PP_STATUS) & mask) == value, 5000, 10)) {
+               DRM_ERROR("Panel status timeout: status %08x control %08x\n",
+                         I915_READ(PCH_PP_STATUS),
+                         I915_READ(PCH_PP_CONTROL));
        }
+}
 
-       off_time = intel_dp->panel_off_jiffies + msecs_to_jiffies(intel_dp->panel_power_down_delay);
-       if (time_after(jiffies, off_time)) {
-               DRM_DEBUG_KMS("Time already passed");
-               return;
-       }
-       delay = jiffies_to_msecs(off_time - jiffies);
-       if (delay > intel_dp->panel_power_down_delay)
-               delay = intel_dp->panel_power_down_delay;
-       DRM_DEBUG_KMS("Waiting an additional %ld ms\n", delay);
-       msleep(delay);
+static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
+{
+       DRM_DEBUG_KMS("Wait for panel power on\n");
+       ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
+}
+
+static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
+{
+       DRM_DEBUG_KMS("Wait for panel power off time\n");
+       ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
+}
+
+static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
+{
+       DRM_DEBUG_KMS("Wait for panel power cycle\n");
+       ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
+}
+
+
+/* Read the current pp_control value, unlocking the register if it
+ * is locked
+ */
+
+static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
+{
+       u32     control = I915_READ(PCH_PP_CONTROL);
+
+       control &= ~PANEL_UNLOCK_MASK;
+       control |= PANEL_UNLOCK_REGS;
+       return control;
 }
 
 static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
@@ -921,15 +975,16 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
             "eDP VDD already requested on\n");
 
        intel_dp->want_panel_vdd = true;
+
        if (ironlake_edp_have_panel_vdd(intel_dp)) {
                DRM_DEBUG_KMS("eDP VDD already on\n");
                return;
        }
 
-       ironlake_wait_panel_off(intel_dp);
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
+       if (!ironlake_edp_have_panel_power(intel_dp))
+               ironlake_wait_panel_power_cycle(intel_dp);
+
+       pp = ironlake_get_pp_control(dev_priv);
        pp |= EDP_FORCE_VDD;
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
@@ -952,9 +1007,7 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
        u32 pp;
 
        if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
-               pp = I915_READ(PCH_PP_CONTROL);
-               pp &= ~PANEL_UNLOCK_MASK;
-               pp |= PANEL_UNLOCK_REGS;
+               pp = ironlake_get_pp_control(dev_priv);
                pp &= ~EDP_FORCE_VDD;
                I915_WRITE(PCH_PP_CONTROL, pp);
                POSTING_READ(PCH_PP_CONTROL);
@@ -962,7 +1015,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
                /* Make sure sequencer is idle before allowing subsequent activity */
                DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
                              I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
-               intel_dp->panel_off_jiffies = jiffies;
+
+               msleep(intel_dp->panel_power_down_delay);
        }
 }
 
@@ -972,9 +1026,9 @@ static void ironlake_panel_vdd_work(struct work_struct *__work)
                                                 struct intel_dp, panel_vdd_work);
        struct drm_device *dev = intel_dp->base.base.dev;
 
-       mutex_lock(&dev->struct_mutex);
+       mutex_lock(&dev->mode_config.mutex);
        ironlake_panel_vdd_off_sync(intel_dp);
-       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&dev->mode_config.mutex);
 }
 
 static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
@@ -984,7 +1038,7 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
        DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);
        WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on");
-       
+
        intel_dp->want_panel_vdd = false;
 
        if (sync) {
@@ -1000,23 +1054,25 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
        }
 }
 
-/* Returns true if the panel was already on when called */
 static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE;
+       u32 pp;
 
        if (!is_edp(intel_dp))
                return;
-       if (ironlake_edp_have_panel_power(intel_dp))
+
+       DRM_DEBUG_KMS("Turn eDP power on\n");
+
+       if (ironlake_edp_have_panel_power(intel_dp)) {
+               DRM_DEBUG_KMS("eDP power already on\n");
                return;
+       }
 
-       ironlake_wait_panel_off(intel_dp);
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
+       ironlake_wait_panel_power_cycle(intel_dp);
 
+       pp = ironlake_get_pp_control(dev_priv);
        if (IS_GEN5(dev)) {
                /* ILK workaround: disable reset around power sequence */
                pp &= ~PANEL_POWER_RESET;
@@ -1025,13 +1081,13 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
        }
 
        pp |= POWER_TARGET_ON;
+       if (!IS_GEN5(dev))
+               pp |= PANEL_POWER_RESET;
+
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
 
-       if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask,
-                    5000))
-               DRM_ERROR("panel on wait timed out: 0x%08x\n",
-                         I915_READ(PCH_PP_STATUS));
+       ironlake_wait_panel_on(intel_dp);
 
        if (IS_GEN5(dev)) {
                pp |= PANEL_POWER_RESET; /* restore panel reset bit */
@@ -1040,46 +1096,25 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
        }
 }
 
-static void ironlake_edp_panel_off(struct drm_encoder *encoder)
+static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 {
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       struct drm_device *dev = encoder->dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK |
-               PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK;
+       u32 pp;
 
        if (!is_edp(intel_dp))
                return;
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
 
-       if (IS_GEN5(dev)) {
-               /* ILK workaround: disable reset around power sequence */
-               pp &= ~PANEL_POWER_RESET;
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
-       }
+       DRM_DEBUG_KMS("Turn eDP power off\n");
 
-       intel_dp->panel_off_jiffies = jiffies;
+       WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n");
 
-       if (IS_GEN5(dev)) {
-               pp &= ~POWER_TARGET_ON;
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
-               pp &= ~POWER_TARGET_ON;
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
-               msleep(intel_dp->panel_power_cycle_delay);
-
-               if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
-                       DRM_ERROR("panel off wait timed out: 0x%08x\n",
-                                 I915_READ(PCH_PP_STATUS));
+       pp = ironlake_get_pp_control(dev_priv);
+       pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+       I915_WRITE(PCH_PP_CONTROL, pp);
+       POSTING_READ(PCH_PP_CONTROL);
 
-               pp |= PANEL_POWER_RESET; /* restore panel reset bit */
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
-       }
+       ironlake_wait_panel_off(intel_dp);
 }
 
 static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1099,9 +1134,7 @@ static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
         * allowing it to appear.
         */
        msleep(intel_dp->backlight_on_delay);
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
+       pp = ironlake_get_pp_control(dev_priv);
        pp |= EDP_BLC_ENABLE;
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
@@ -1117,9 +1150,7 @@ static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
                return;
 
        DRM_DEBUG_KMS("\n");
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
+       pp = ironlake_get_pp_control(dev_priv);
        pp &= ~EDP_BLC_ENABLE;
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
@@ -1187,17 +1218,18 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
 {
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
+       ironlake_edp_backlight_off(intel_dp);
+       ironlake_edp_panel_off(intel_dp);
+
        /* Wake up the sink first */
        ironlake_edp_panel_vdd_on(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+       intel_dp_link_down(intel_dp);
        ironlake_edp_panel_vdd_off(intel_dp, false);
 
        /* Make sure the panel is off before trying to
         * change the mode
         */
-       ironlake_edp_backlight_off(intel_dp);
-       intel_dp_link_down(intel_dp);
-       ironlake_edp_panel_off(encoder);
 }
 
 static void intel_dp_commit(struct drm_encoder *encoder)
@@ -1211,7 +1243,6 @@ static void intel_dp_commit(struct drm_encoder *encoder)
        intel_dp_start_link_train(intel_dp);
        ironlake_edp_panel_on(intel_dp);
        ironlake_edp_panel_vdd_off(intel_dp, true);
-
        intel_dp_complete_link_train(intel_dp);
        ironlake_edp_backlight_on(intel_dp);
 
@@ -1230,16 +1261,20 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
        uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
        if (mode != DRM_MODE_DPMS_ON) {
+               ironlake_edp_backlight_off(intel_dp);
+               ironlake_edp_panel_off(intel_dp);
+
                ironlake_edp_panel_vdd_on(intel_dp);
-               if (is_edp(intel_dp))
-                       ironlake_edp_backlight_off(intel_dp);
                intel_dp_sink_dpms(intel_dp, mode);
                intel_dp_link_down(intel_dp);
-               ironlake_edp_panel_off(encoder);
-               if (is_edp(intel_dp) && !is_pch_edp(intel_dp))
-                       ironlake_edp_pll_off(encoder);
                ironlake_edp_panel_vdd_off(intel_dp, false);
+
+               if (is_cpu_edp(intel_dp))
+                       ironlake_edp_pll_off(encoder);
        } else {
+               if (is_cpu_edp(intel_dp))
+                       ironlake_edp_pll_on(encoder);
+
                ironlake_edp_panel_vdd_on(intel_dp);
                intel_dp_sink_dpms(intel_dp, mode);
                if (!(dp_reg & DP_PORT_EN)) {
@@ -1247,7 +1282,6 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
                        ironlake_edp_panel_on(intel_dp);
                        ironlake_edp_panel_vdd_off(intel_dp, true);
                        intel_dp_complete_link_train(intel_dp);
-                       ironlake_edp_backlight_on(intel_dp);
                } else
                        ironlake_edp_panel_vdd_off(intel_dp, false);
                ironlake_edp_backlight_on(intel_dp);
@@ -1285,11 +1319,11 @@ intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address,
  * link status information
  */
 static bool
-intel_dp_get_link_status(struct intel_dp *intel_dp)
+intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
        return intel_dp_aux_native_read_retry(intel_dp,
                                              DP_LANE0_1_STATUS,
-                                             intel_dp->link_status,
+                                             link_status,
                                              DP_LINK_STATUS_SIZE);
 }
 
@@ -1301,27 +1335,25 @@ intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
 }
 
 static uint8_t
-intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+intel_get_adjust_request_voltage(uint8_t adjust_request[2],
                                 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);
+       uint8_t l = adjust_request[lane>>1];
 
        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],
+intel_get_adjust_request_pre_emphasis(uint8_t adjust_request[2],
                                      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);
+       uint8_t l = adjust_request[lane>>1];
 
        return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
 }
@@ -1344,6 +1376,7 @@ static char       *link_train_names[] = {
  * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
  */
 #define I830_DP_VOLTAGE_MAX        DP_TRAIN_VOLTAGE_SWING_800
+#define I830_DP_VOLTAGE_MAX_CPT            DP_TRAIN_VOLTAGE_SWING_1200
 
 static uint8_t
 intel_dp_pre_emphasis_max(uint8_t voltage_swing)
@@ -1362,15 +1395,18 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
 }
 
 static void
-intel_get_adjust_train(struct intel_dp *intel_dp)
+intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
+       struct drm_device *dev = intel_dp->base.base.dev;
        uint8_t v = 0;
        uint8_t p = 0;
        int lane;
+       uint8_t *adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS);
+       int voltage_max;
 
        for (lane = 0; lane < intel_dp->lane_count; lane++) {
-               uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane);
-               uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
+               uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane);
+               uint8_t this_p = intel_get_adjust_request_pre_emphasis(adjust_request, lane);
 
                if (this_v > v)
                        v = this_v;
@@ -1378,8 +1414,12 @@ intel_get_adjust_train(struct intel_dp *intel_dp)
                        p = this_p;
        }
 
-       if (v >= I830_DP_VOLTAGE_MAX)
-               v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+       if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
+               voltage_max = I830_DP_VOLTAGE_MAX_CPT;
+       else
+               voltage_max = I830_DP_VOLTAGE_MAX;
+       if (v >= voltage_max)
+               v = 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;
@@ -1389,7 +1429,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp)
 }
 
 static uint32_t
-intel_dp_signal_levels(uint8_t train_set, int lane_count)
+intel_dp_signal_levels(uint8_t train_set)
 {
        uint32_t        signal_levels = 0;
 
@@ -1458,9 +1498,8 @@ 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);
+       uint8_t l = link_status[lane>>1];
 
        return (l >> s) & 0xf;
 }
@@ -1485,18 +1524,18 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count
                         DP_LANE_CHANNEL_EQ_DONE|\
                         DP_LANE_SYMBOL_LOCKED)
 static bool
-intel_channel_eq_ok(struct intel_dp *intel_dp)
+intel_channel_eq_ok(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
        uint8_t lane_align;
        uint8_t lane_status;
        int lane;
 
-       lane_align = intel_dp_link_status(intel_dp->link_status,
+       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 < intel_dp->lane_count; lane++) {
-               lane_status = intel_get_lane_status(intel_dp->link_status, lane);
+               lane_status = intel_get_lane_status(link_status, lane);
                if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
                        return false;
        }
@@ -1521,8 +1560,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 
        ret = intel_dp_aux_native_write(intel_dp,
                                        DP_TRAINING_LANE0_SET,
-                                       intel_dp->train_set, 4);
-       if (ret != 4)
+                                       intel_dp->train_set,
+                                       intel_dp->lane_count);
+       if (ret != intel_dp->lane_count)
                return false;
 
        return true;
@@ -1538,7 +1578,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
        int i;
        uint8_t voltage;
        bool clock_recovery = false;
-       int tries;
+       int voltage_tries, loop_tries;
        u32 reg;
        uint32_t DP = intel_dp->DP;
 
@@ -1565,16 +1605,20 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                DP &= ~DP_LINK_TRAIN_MASK;
        memset(intel_dp->train_set, 0, 4);
        voltage = 0xff;
-       tries = 0;
+       voltage_tries = 0;
+       loop_tries = 0;
        clock_recovery = false;
        for (;;) {
                /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
+               uint8_t     link_status[DP_LINK_STATUS_SIZE];
                uint32_t    signal_levels;
-               if (IS_GEN6(dev) && is_edp(intel_dp)) {
+
+               if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
                        signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
-                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
+                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
+                       DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
@@ -1590,10 +1634,13 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                /* Set training pattern 1 */
 
                udelay(100);
-               if (!intel_dp_get_link_status(intel_dp))
+               if (!intel_dp_get_link_status(intel_dp, link_status)) {
+                       DRM_ERROR("failed to get link status\n");
                        break;
+               }
 
-               if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+               if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
+                       DRM_DEBUG_KMS("clock recovery OK\n");
                        clock_recovery = true;
                        break;
                }
@@ -1602,20 +1649,30 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                for (i = 0; i < intel_dp->lane_count; i++)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
-               if (i == intel_dp->lane_count)
-                       break;
+               if (i == intel_dp->lane_count) {
+                       ++loop_tries;
+                       if (loop_tries == 5) {
+                               DRM_DEBUG_KMS("too many full retries, give up\n");
+                               break;
+                       }
+                       memset(intel_dp->train_set, 0, 4);
+                       voltage_tries = 0;
+                       continue;
+               }
 
                /* Check to see if we've tried the same voltage 5 times */
                if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
-                       ++tries;
-                       if (tries == 5)
+                       ++voltage_tries;
+                       if (voltage_tries == 5) {
+                               DRM_DEBUG_KMS("too many voltage retries, give up\n");
                                break;
+                       }
                } else
-                       tries = 0;
+                       voltage_tries = 0;
                voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
                /* Compute new intel_dp->train_set as requested by target */
-               intel_get_adjust_train(intel_dp);
+               intel_get_adjust_train(intel_dp, link_status);
        }
 
        intel_dp->DP = DP;
@@ -1638,6 +1695,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
        for (;;) {
                /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
                uint32_t    signal_levels;
+               uint8_t     link_status[DP_LINK_STATUS_SIZE];
 
                if (cr_tries > 5) {
                        DRM_ERROR("failed to train DP, aborting\n");
@@ -1645,11 +1703,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                        break;
                }
 
-               if (IS_GEN6(dev) && is_edp(intel_dp)) {
+               if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
                        signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
-                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
+                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
@@ -1665,17 +1723,17 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                        break;
 
                udelay(400);
-               if (!intel_dp_get_link_status(intel_dp))
+               if (!intel_dp_get_link_status(intel_dp, link_status))
                        break;
 
                /* Make sure clock is still ok */
-               if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+               if (!intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
                        intel_dp_start_link_train(intel_dp);
                        cr_tries++;
                        continue;
                }
 
-               if (intel_channel_eq_ok(intel_dp)) {
+               if (intel_channel_eq_ok(intel_dp, link_status)) {
                        channel_eq = true;
                        break;
                }
@@ -1690,7 +1748,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                }
 
                /* Compute new intel_dp->train_set as requested by target */
-               intel_get_adjust_train(intel_dp);
+               intel_get_adjust_train(intel_dp, link_status);
                ++tries;
        }
 
@@ -1735,8 +1793,12 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
        msleep(17);
 
-       if (is_edp(intel_dp))
-               DP |= DP_LINK_TRAIN_OFF;
+       if (is_edp(intel_dp)) {
+               if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
+                       DP |= DP_LINK_TRAIN_OFF_CPT;
+               else
+                       DP |= DP_LINK_TRAIN_OFF;
+       }
 
        if (!HAS_PCH_CPT(dev) &&
            I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
@@ -1822,6 +1884,7 @@ static void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
        u8 sink_irq_vector;
+       u8 link_status[DP_LINK_STATUS_SIZE];
 
        if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
                return;
@@ -1830,7 +1893,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
                return;
 
        /* Try to read receiver status if the link appears to be up */
-       if (!intel_dp_get_link_status(intel_dp)) {
+       if (!intel_dp_get_link_status(intel_dp, link_status)) {
                intel_dp_link_down(intel_dp);
                return;
        }
@@ -1855,7 +1918,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
                        DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
        }
 
-       if (!intel_channel_eq_ok(intel_dp)) {
+       if (!intel_channel_eq_ok(intel_dp, link_status)) {
                DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
                              drm_get_encoder_name(&intel_dp->base.base));
                intel_dp_start_link_train(intel_dp);
@@ -2179,7 +2242,8 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
                        continue;
 
                intel_dp = enc_to_intel_dp(encoder);
-               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
+               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
+                   intel_dp->base.type == INTEL_OUTPUT_EDP)
                        return intel_dp->output_reg;
        }
 
@@ -2321,7 +2385,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
                cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
                        PANEL_LIGHT_ON_DELAY_SHIFT;
-               
+
                cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
                        PANEL_LIGHT_OFF_DELAY_SHIFT;
 
@@ -2354,11 +2418,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
                              intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
 
-               intel_dp->panel_off_jiffies = jiffies - intel_dp->panel_power_down_delay;
-
                ironlake_edp_panel_vdd_on(intel_dp);
                ret = intel_dp_get_dpcd(intel_dp);
                ironlake_edp_panel_vdd_off(intel_dp, false);
+
                if (ret) {
                        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
                                dev_priv->no_aux_handshake =
index 499d4c0dbeebd93f944d338ffc29184ed5103617..21f60b7d69a30819d13f7e0fd942e3ebe4fe7bbd 100644 (file)
@@ -326,7 +326,8 @@ static int intel_panel_update_status(struct backlight_device *bd)
 static int intel_panel_get_brightness(struct backlight_device *bd)
 {
        struct drm_device *dev = bl_get_data(bd);
-       return intel_panel_get_backlight(dev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       return dev_priv->backlight_level;
 }
 
 static const struct backlight_ops intel_panel_bl_ops = {
index 032a820981363c3d4422fba06ab93d7c8c0f1621..5fc201b49d3070721cade7821c3d259f15b5f441 100644 (file)
@@ -640,10 +640,9 @@ static int
 nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       uint32_t reg0 = nv_rd32(dev, reg + 0);
-       uint32_t reg1 = nv_rd32(dev, reg + 4);
        struct nouveau_pll_vals pll;
        struct pll_lims pll_limits;
+       u32 ctrl, mask, coef;
        int ret;
 
        ret = get_pll_limits(dev, reg, &pll_limits);
@@ -654,15 +653,20 @@ nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
        if (!clk)
                return -ERANGE;
 
-       reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
-       reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
-
-       if (dev_priv->vbios.execute) {
-               still_alive();
-               nv_wr32(dev, reg + 4, reg1);
-               nv_wr32(dev, reg + 0, reg0);
+       coef = pll.N1 << 8 | pll.M1;
+       ctrl = pll.log2P << 16;
+       mask = 0x00070000;
+       if (reg == 0x004008) {
+               mask |= 0x01f80000;
+               ctrl |= (pll_limits.log2p_bias << 19);
+               ctrl |= (pll.log2P << 22);
        }
 
+       if (!dev_priv->vbios.execute)
+               return 0;
+
+       nv_mask(dev, reg + 0, mask, ctrl);
+       nv_wr32(dev, reg + 4, coef);
        return 0;
 }
 
index 7226f419e178b64e76d9a65a7d341f1de874b746..7cc37e69086012594a1dff3a2e255f66e396e656 100644 (file)
@@ -148,7 +148,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
 
        if (dev_priv->card_type == NV_10 &&
            nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
-           nvbo->bo.mem.num_pages < vram_pages / 2) {
+           nvbo->bo.mem.num_pages < vram_pages / 4) {
                /*
                 * Make sure that the color and depth buffers are handled
                 * by independent memory controller units. Up to a 9x
index a319d5646ea9c98430eddab17c0a45f0f8307b3f..bb6ec9ef8676a6300f6de6fc221cc5b5c7c7199e 100644 (file)
@@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
        INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
        INIT_LIST_HEAD(&chan->nvsw.flip);
        INIT_LIST_HEAD(&chan->fence.pending);
+       spin_lock_init(&chan->fence.lock);
 
        /* setup channel's memory and vm */
        ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
index e0d275e1c96c05c302693c49b7093cde95eccc40..cea6696b19064e48a7c4f1e94bef793377962db8 100644 (file)
@@ -710,7 +710,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
        case OUTPUT_DP:
                max_clock  = nv_encoder->dp.link_nr;
                max_clock *= nv_encoder->dp.link_bw;
-               clock = clock * nouveau_connector_bpp(connector) / 8;
+               clock = clock * nouveau_connector_bpp(connector) / 10;
                break;
        default:
                BUG_ON(1);
index 14a8627efe4d0499515d596cbaf665fbfbade690..3a4cc32b9e44c44f92fab174792778def49197f4 100644 (file)
@@ -487,6 +487,7 @@ int nouveau_fbcon_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_fbdev *nfbdev;
+       int preferred_bpp;
        int ret;
 
        nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
@@ -505,7 +506,15 @@ int nouveau_fbcon_init(struct drm_device *dev)
        }
 
        drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
-       drm_fb_helper_initial_config(&nfbdev->helper, 32);
+
+       if (dev_priv->vram_size <= 32 * 1024 * 1024)
+               preferred_bpp = 8;
+       else if (dev_priv->vram_size <= 64 * 1024 * 1024)
+               preferred_bpp = 16;
+       else
+               preferred_bpp = 32;
+
+       drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp);
        return 0;
 }
 
index 81116cfea275f70fc5011a23c4284b51fc2fcf4a..2f6daae68b9d7e24830bb9f2cc5e5af09cbe4f8b 100644 (file)
@@ -539,8 +539,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
                        return ret;
        }
 
-       INIT_LIST_HEAD(&chan->fence.pending);
-       spin_lock_init(&chan->fence.lock);
        atomic_set(&chan->fence.last_sequence_irq, 0);
        return 0;
 }
index c6143df48b9f8a385d97e2b4d045c891f399ad90..d39b2202b197521473129d8c5e3cf1ccd6d34031 100644 (file)
@@ -333,7 +333,7 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what,
 
        NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
 
-       for (i = 0; info[i].addr; i++) {
+       for (i = 0; i2c && info[i].addr; i++) {
                if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
                    (!match || match(i2c, &info[i]))) {
                        NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
index 9f178aa94162cdc69ac943066272fd3ba899a062..33d03fbf00df56c7523bf8909168d267f0a1d197 100644 (file)
@@ -239,7 +239,7 @@ nouveau_perf_init(struct drm_device *dev)
        if(version == 0x15) {
                memtimings->timing =
                                kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
-               if(!memtimings) {
+               if (!memtimings->timing) {
                        NV_WARN(dev,"Could not allocate memtiming table\n");
                        return;
                }
index 82478e0998e5c7bb1109e17a37c90005491fddbf..d8831ab42bb90344a28b8a146624aa4aca69d8c5 100644 (file)
@@ -579,6 +579,14 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out_display_early;
 
+       /* workaround an odd issue on nvc1 by disabling the device's
+        * nosnoop capability.  hopefully won't cause issues until a
+        * better fix is found - assuming there is one...
+        */
+       if (dev_priv->chipset == 0xc1) {
+               nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
+       }
+
        nouveau_pm_init(dev);
 
        ret = engine->vram.init(dev);
@@ -1102,12 +1110,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
        dev_priv->noaccel = !!nouveau_noaccel;
        if (nouveau_noaccel == -1) {
                switch (dev_priv->chipset) {
-               case 0xc1: /* known broken */
-               case 0xc8: /* never tested */
+#if 0
+               case 0xXX: /* known broken */
                        NV_INFO(dev, "acceleration disabled by default, pass "
                                     "noaccel=0 to force enable\n");
                        dev_priv->noaccel = true;
                        break;
+#endif
                default:
                        dev_priv->noaccel = false;
                        break;
index bbc0b9c7e1f7f53ba099c57a8c408024feb32fca..e676b0d534786ee140017691b83c4580e0e6bbc3 100644 (file)
@@ -57,12 +57,14 @@ read_pll_2(struct drm_device *dev, u32 reg)
        int P = (ctrl & 0x00070000) >> 16;
        u32 ref = 27000, clk = 0;
 
-       if (ctrl & 0x80000000)
+       if ((ctrl & 0x80000000) && M1) {
                clk = ref * N1 / M1;
-
-       if (!(ctrl & 0x00000100)) {
-               if (ctrl & 0x40000000)
-                       clk = clk * N2 / M2;
+               if ((ctrl & 0x40000100) == 0x40000000) {
+                       if (M2)
+                               clk = clk * N2 / M2;
+                       else
+                               clk = 0;
+               }
        }
 
        return clk >> P;
@@ -177,6 +179,11 @@ nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
        }
 
        /* memory clock */
+       if (!perflvl->memory) {
+               info->mpll_ctrl = 0x00000000;
+               goto out;
+       }
+
        ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory,
                            &N1, &M1, &N2, &M2, &log2P);
        if (ret < 0)
@@ -264,6 +271,9 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state)
        mdelay(5);
        nv_mask(dev, 0x00c040, 0x00000333, info->ctrl);
 
+       if (!info->mpll_ctrl)
+               goto resume;
+
        /* wait for vblank start on active crtcs, disable memory access */
        for (i = 0; i < 2; i++) {
                if (!(crtc_mask & (1 << i)))
index 8c979b31ff61b36bf8714fd6b5baa3bad58d268e..ac601f7c4e1a01c7175c9a201f3474e958ef98b7 100644 (file)
@@ -131,8 +131,8 @@ nv50_graph_init(struct drm_device *dev, int engine)
        NV_DEBUG(dev, "\n");
 
        /* master reset */
-       nv_mask(dev, 0x000200, 0x00200100, 0x00000000);
-       nv_mask(dev, 0x000200, 0x00200100, 0x00200100);
+       nv_mask(dev, 0x000200, 0x00201000, 0x00000000);
+       nv_mask(dev, 0x000200, 0x00201000, 0x00201000);
        nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
 
        /* reset/enable traps and interrupts */
index d05c2c3b244491001dbcba21c2d3dc32fc3a7d59..4b46d69685664fcc14f096c644395a43316a6421 100644 (file)
@@ -601,7 +601,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
                                        gr_def(ctx, offset + 0x1c, 0x00880000);
                                        break;
                                case 0x86:
-                                       gr_def(ctx, offset + 0x1c, 0x008c0000);
+                                       gr_def(ctx, offset + 0x1c, 0x018c0000);
                                        break;
                                case 0x92:
                                case 0x96:
index 9da23838e63e0d04d6e24f51e8a45e835cfb2979..2e45e57fd8698e03a2b8fdf3fcd04b69ddf86290 100644 (file)
@@ -160,7 +160,7 @@ nv50_vram_rblock(struct drm_device *dev)
        colbits  =  (r4 & 0x0000f000) >> 12;
        rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
        rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
-       banks    = ((r4 & 0x01000000) ? 8 : 4);
+       banks    = 1 << (((r4 & 0x03000000) >> 24) + 2);
 
        rowsize = parts * banks * (1 << colbits) * 8;
        predicted = rowsize << rowbitsa;
index bbdbc51830c8df10c8475c9c82e888d0a1adf1cc..a74e501afd25b44b7315d497f8ca30908dcb3995 100644 (file)
@@ -157,8 +157,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
        struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
        struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
        struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i = 0, gpc, tp, ret;
-       u32 magic;
 
        ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
                                 &grch->unk408004);
@@ -207,14 +207,37 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
        nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
        nv_wo32(grch->mmio, i++ * 4, 0x80000018);
 
-       magic = 0x02180000;
-       nv_wo32(grch->mmio, i++ * 4, 0x00405830);
-       nv_wo32(grch->mmio, i++ * 4, magic);
-       for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-               for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
-                       u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
-                       nv_wo32(grch->mmio, i++ * 4, reg);
-                       nv_wo32(grch->mmio, i++ * 4, magic);
+       if (dev_priv->chipset != 0xc1) {
+               u32 magic = 0x02180000;
+               nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+               nv_wo32(grch->mmio, i++ * 4, magic);
+               for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+                       for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+                               u32 reg = TP_UNIT(gpc, tp, 0x520);
+                               nv_wo32(grch->mmio, i++ * 4, reg);
+                               nv_wo32(grch->mmio, i++ * 4, magic);
+                               magic += 0x0324;
+                       }
+               }
+       } else {
+               u32 magic = 0x02180000;
+               nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+               nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218);
+               nv_wo32(grch->mmio, i++ * 4, 0x004064c4);
+               nv_wo32(grch->mmio, i++ * 4, 0x0086ffff);
+               for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+                       for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+                               u32 reg = TP_UNIT(gpc, tp, 0x520);
+                               nv_wo32(grch->mmio, i++ * 4, reg);
+                               nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic);
+                               magic += 0x0324;
+                       }
+                       for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+                               u32 reg = TP_UNIT(gpc, tp, 0x544);
+                               nv_wo32(grch->mmio, i++ * 4, reg);
+                               nv_wo32(grch->mmio, i++ * 4, magic);
+                               magic += 0x0324;
+                       }
                }
        }
 
index dd0e6a736b3b9254933e2d58b51c0502bf353aa8..96b0b93d94ca8b11466145ddd2c2ce050eee5ffb 100644 (file)
@@ -1812,6 +1812,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
                /* calculate first set of magics */
                memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 
+               gpc = -1;
                for (tp = 0; tp < priv->tp_total; tp++) {
                        do {
                                gpc = (gpc + 1) % priv->gpc_nr;
@@ -1861,30 +1862,26 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
 
        if (1) {
                u32 tp_mask = 0, tp_set = 0;
-               u8  tpnr[GPC_MAX];
+               u8  tpnr[GPC_MAX], a, b;
 
                memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
                for (gpc = 0; gpc < priv->gpc_nr; gpc++)
                        tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8);
 
-               gpc = -1;
-               for (i = 0, gpc = -1; i < 32; i++) {
-                       int ltp = i * (priv->tp_total - 1) / 32;
-
-                       do {
-                               gpc = (gpc + 1) % priv->gpc_nr;
-                       } while (!tpnr[gpc]);
-                       tp = priv->tp_nr[gpc] - tpnr[gpc]--;
+               for (i = 0, gpc = -1, b = -1; i < 32; i++) {
+                       a = (i * (priv->tp_total - 1)) / 32;
+                       if (a != b) {
+                               b = a;
+                               do {
+                                       gpc = (gpc + 1) % priv->gpc_nr;
+                               } while (!tpnr[gpc]);
+                               tp = priv->tp_nr[gpc] - tpnr[gpc]--;
 
-                       tp_set |= 1 << ((gpc * 8) + tp);
+                               tp_set |= 1 << ((gpc * 8) + tp);
+                       }
 
-                       do {
-                               nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
-                               tp_set ^= tp_mask;
-                               nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set);
-                               tp_set ^= tp_mask;
-                       } while (ltp == (++i * (priv->tp_total - 1) / 32));
-                       i--;
+                       nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
+                       nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask);
                }
        }
 
index edbfe9360ae2f0a2703176c0ea1fcd1dfeed83a0..ce984d573a51d03bb6df5b6cc171ed4721a60533 100644 (file)
@@ -43,7 +43,7 @@ static const u8 types[256] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
-       3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
+       3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
        3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
        3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
@@ -110,22 +110,26 @@ nvc0_vram_init(struct drm_device *dev)
        u32 bsize = nv_rd32(dev, 0x10f20c);
        u32 offset, length;
        bool uniform = true;
-       int ret, i;
+       int ret, part;
 
        NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
        NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
 
        /* read amount of vram attached to each memory controller */
-       for (i = 0; i < parts; i++) {
-               u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000));
+       part = 0;
+       while (parts) {
+               u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000));
+               if (psize == 0)
+                       continue;
+               parts--;
+
                if (psize != bsize) {
                        if (psize < bsize)
                                bsize = psize;
                        uniform = false;
                }
 
-               NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize);
-
+               NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize);
                dev_priv->vram_size += (u64)psize << 20;
        }
 
index 9f363e0c4b6082561295eb5f5e8a78559e42dccd..cf8b4bc3e73ddfc6804beba647fb4a8b1988ccc6 100644 (file)
@@ -70,7 +70,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
        r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
        r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
        evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
-       radeon_trace_points.o ni.o cayman_blit_shaders.o
+       radeon_trace_points.o ni.o cayman_blit_shaders.o atombios_encoders.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
index a515b2a09d856c1c49d2a38096dda8c76ccc92b5..87631fede1f8ed2a750419200688c151f552e7e6 100644 (file)
@@ -558,7 +558,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                bpc = connector->display_info.bpc;
                        encoder_mode = atombios_get_encoder_mode(encoder);
                        if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
-                           radeon_encoder_is_dp_bridge(encoder)) {
+                           (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
                                if (connector) {
                                        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                                        struct radeon_connector_atom_dig *dig_connector =
@@ -638,44 +638,29 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                if (ss_enabled && ss->percentage)
                                        args.v3.sInput.ucDispPllConfig |=
                                                DISPPLL_CONFIG_SS_ENABLE;
-                               if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT) ||
-                                   radeon_encoder_is_dp_bridge(encoder)) {
+                               if (ENCODER_MODE_IS_DP(encoder_mode)) {
+                                       args.v3.sInput.ucDispPllConfig |=
+                                               DISPPLL_CONFIG_COHERENT_MODE;
+                                       /* 16200 or 27000 */
+                                       args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
+                               } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
                                        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-                                       if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+                                       if (encoder_mode == ATOM_ENCODER_MODE_HDMI)
+                                               /* deep color support */
+                                               args.v3.sInput.usPixelClock =
+                                                       cpu_to_le16((mode->clock * bpc / 8) / 10);
+                                       if (dig->coherent_mode)
                                                args.v3.sInput.ucDispPllConfig |=
                                                        DISPPLL_CONFIG_COHERENT_MODE;
-                                               /* 16200 or 27000 */
-                                               args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
-                                       } else {
-                                               if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
-                                                       /* deep color support */
-                                                       args.v3.sInput.usPixelClock =
-                                                               cpu_to_le16((mode->clock * bpc / 8) / 10);
-                                               }
-                                               if (dig->coherent_mode)
-                                                       args.v3.sInput.ucDispPllConfig |=
-                                                               DISPPLL_CONFIG_COHERENT_MODE;
-                                               if (mode->clock > 165000)
-                                                       args.v3.sInput.ucDispPllConfig |=
-                                                               DISPPLL_CONFIG_DUAL_LINK;
-                                       }
-                               } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                                       if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+                                       if (mode->clock > 165000)
                                                args.v3.sInput.ucDispPllConfig |=
-                                                       DISPPLL_CONFIG_COHERENT_MODE;
-                                               /* 16200 or 27000 */
-                                               args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
-                                       } else if (encoder_mode != ATOM_ENCODER_MODE_LVDS) {
-                                               if (mode->clock > 165000)
-                                                       args.v3.sInput.ucDispPllConfig |=
-                                                               DISPPLL_CONFIG_DUAL_LINK;
-                                       }
+                                                       DISPPLL_CONFIG_DUAL_LINK;
                                }
-                               if (radeon_encoder_is_dp_bridge(encoder)) {
-                                       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-                                       struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
-                                       args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id;
-                               else
+                               if (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
+                                   ENCODER_OBJECT_ID_NONE)
+                                       args.v3.sInput.ucExtTransmitterID =
+                                               radeon_encoder_get_dp_bridge_encoder_id(encoder);
+                               else
                                        args.v3.sInput.ucExtTransmitterID = 0;
 
                                atom_execute_table(rdev->mode_info.atom_context,
@@ -945,6 +930,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                bpc = connector->display_info.bpc;
 
                switch (encoder_mode) {
+               case ATOM_ENCODER_MODE_DP_MST:
                case ATOM_ENCODER_MODE_DP:
                        /* DP/eDP */
                        dp_clock = dig_connector->dp_clock / 10;
@@ -1450,7 +1436,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                                 * PPLL/DCPLL programming and only program the DP DTO for the
                                 * crtc virtual pixel clock.
                                 */
-                               if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) {
+                               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
                                        if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk)
                                                return ATOM_PPLL_INVALID;
                                }
@@ -1536,12 +1522,6 @@ static bool atombios_crtc_mode_fixup(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;
-
-       /* adjust pm to upcoming mode change */
-       radeon_pm_compute_clocks(rdev);
-
        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
                return false;
        return true;
index 79e8ebc0530723e9df8a8aa5f448b3b8068fab62..6fb335a4fddafee8bdf3bfc0bbe48e54df265106 100644 (file)
@@ -283,7 +283,7 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                }
        }
 
-       DRM_ERROR("aux i2c too many retries, giving up\n");
+       DRM_DEBUG_KMS("aux i2c too many retries, giving up\n");
        return -EREMOTEIO;
 }
 
@@ -482,7 +482,8 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
        int bpp = convert_bpc_to_bpp(connector->display_info.bpc);
        int lane_num, max_pix_clock;
 
-       if (radeon_connector_encoder_is_dp_bridge(connector))
+       if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+           ENCODER_OBJECT_ID_NUTMEG)
                return 270000;
 
        lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock);
@@ -553,17 +554,32 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
 
        if (!ASIC_IS_DCE4(rdev))
                return;
 
-       if (radeon_connector_encoder_is_dp_bridge(connector))
+       if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+           ENCODER_OBJECT_ID_NUTMEG)
                panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
+       else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+                ENCODER_OBJECT_ID_TRAVIS)
+               panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+       else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+               u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+               if (tmp & 1)
+                       panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+       }
 
        atombios_dig_encoder_setup(encoder,
                                   ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
                                   panel_mode);
+
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
+           (panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
+               radeon_write_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
+       }
 }
 
 void radeon_dp_set_link_config(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
new file mode 100644 (file)
index 0000000..39c04c1
--- /dev/null
@@ -0,0 +1,2369 @@
+/*
+ * Copyright 2007-11 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat 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: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "atom.h"
+
+extern int atom_debug;
+
+/* evil but including atombios.h is much worse */
+bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
+                               struct drm_display_mode *mode);
+
+
+static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
+{
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static struct drm_connector *
+radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_connector *connector;
+       struct radeon_connector *radeon_connector;
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               radeon_connector = to_radeon_connector(connector);
+               if (radeon_encoder->devices & radeon_connector->devices)
+                       return connector;
+       }
+       return NULL;
+}
+
+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);
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
+       /* set the active encoder to connector routing */
+       radeon_encoder_set_active_device(encoder);
+       drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+       /* hw bug */
+       if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
+           && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
+               adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
+
+       /* get the native mode for LVDS */
+       if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
+               radeon_panel_mode_fixup(encoder, adjusted_mode);
+
+       /* get the native mode for TV */
+       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
+               struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
+               if (tv_dac) {
+                       if (tv_dac->tv_std == TV_STD_NTSC ||
+                           tv_dac->tv_std == TV_STD_NTSC_J ||
+                           tv_dac->tv_std == TV_STD_PAL_M)
+                               radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
+                       else
+                               radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
+               }
+       }
+
+       if (ASIC_IS_DCE3(rdev) &&
+           ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
+            (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
+               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+               radeon_dp_set_link_config(connector, mode);
+       }
+
+       return true;
+}
+
+static void
+atombios_dac_setup(struct drm_encoder *encoder, int action)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       DAC_ENCODER_CONTROL_PS_ALLOCATION args;
+       int index = 0;
+       struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
+
+       memset(&args, 0, sizeof(args));
+
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+               index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
+               break;
+       }
+
+       args.ucAction = action;
+
+       if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
+               args.ucDacStandard = ATOM_DAC1_PS2;
+       else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+               args.ucDacStandard = ATOM_DAC1_CV;
+       else {
+               switch (dac_info->tv_std) {
+               case TV_STD_PAL:
+               case TV_STD_PAL_M:
+               case TV_STD_SCART_PAL:
+               case TV_STD_SECAM:
+               case TV_STD_PAL_CN:
+                       args.ucDacStandard = ATOM_DAC1_PAL;
+                       break;
+               case TV_STD_NTSC:
+               case TV_STD_NTSC_J:
+               case TV_STD_PAL_60:
+               default:
+                       args.ucDacStandard = ATOM_DAC1_NTSC;
+                       break;
+               }
+       }
+       args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+static void
+atombios_tv_setup(struct drm_encoder *encoder, int action)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       TV_ENCODER_CONTROL_PS_ALLOCATION args;
+       int index = 0;
+       struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
+
+       memset(&args, 0, sizeof(args));
+
+       index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
+
+       args.sTVEncoder.ucAction = action;
+
+       if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+               args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
+       else {
+               switch (dac_info->tv_std) {
+               case TV_STD_NTSC:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
+                       break;
+               case TV_STD_PAL:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
+                       break;
+               case TV_STD_PAL_M:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
+                       break;
+               case TV_STD_PAL_60:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
+                       break;
+               case TV_STD_NTSC_J:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
+                       break;
+               case TV_STD_SCART_PAL:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
+                       break;
+               case TV_STD_SECAM:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
+                       break;
+               case TV_STD_PAL_CN:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
+                       break;
+               default:
+                       args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
+                       break;
+               }
+       }
+
+       args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+union dvo_encoder_control {
+       ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
+       DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
+       DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
+};
+
+void
+atombios_dvo_setup(struct drm_encoder *encoder, int action)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       union dvo_encoder_control args;
+       int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
+       uint8_t frev, crev;
+
+       memset(&args, 0, sizeof(args));
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (frev) {
+       case 1:
+               switch (crev) {
+               case 1:
+                       /* R4xx, R5xx */
+                       args.ext_tmds.sXTmdsEncoder.ucEnable = action;
+
+                       if (radeon_encoder->pixel_clock > 165000)
+                               args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+
+                       args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
+                       break;
+               case 2:
+                       /* RS600/690/740 */
+                       args.dvo.sDVOEncoder.ucAction = action;
+                       args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       /* DFP1, CRT1, TV1 depending on the type of port */
+                       args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
+
+                       if (radeon_encoder->pixel_clock > 165000)
+                               args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
+                       break;
+               case 3:
+                       /* R6xx */
+                       args.dvo_v3.ucAction = action;
+                       args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       args.dvo_v3.ucDVOConfig = 0; /* XXX */
+                       break;
+               default:
+                       DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+                       break;
+               }
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               break;
+       }
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+union lvds_encoder_control {
+       LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
+       LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
+};
+
+void
+atombios_digital_setup(struct drm_encoder *encoder, int action)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+       union lvds_encoder_control args;
+       int index = 0;
+       int hdmi_detected = 0;
+       uint8_t frev, crev;
+
+       if (!dig)
+               return;
+
+       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
+               hdmi_detected = 1;
+
+       memset(&args, 0, sizeof(args));
+
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+               index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+               index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+               else
+                       index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
+               break;
+       }
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (frev) {
+       case 1:
+       case 2:
+               switch (crev) {
+               case 1:
+                       args.v1.ucMisc = 0;
+                       args.v1.ucAction = action;
+                       if (hdmi_detected)
+                               args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+                       args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                               if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
+                                       args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+                               if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+                                       args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
+                       } else {
+                               if (dig->linkb)
+                                       args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
+                               if (radeon_encoder->pixel_clock > 165000)
+                                       args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+                               /*if (pScrn->rgbBits == 8) */
+                               args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
+                       }
+                       break;
+               case 2:
+               case 3:
+                       args.v2.ucMisc = 0;
+                       args.v2.ucAction = action;
+                       if (crev == 3) {
+                               if (dig->coherent_mode)
+                                       args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
+                       }
+                       if (hdmi_detected)
+                               args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+                       args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       args.v2.ucTruncate = 0;
+                       args.v2.ucSpatial = 0;
+                       args.v2.ucTemporal = 0;
+                       args.v2.ucFRC = 0;
+                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                               if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
+                                       args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+                               if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
+                                       args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
+                                       if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+                                               args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
+                               }
+                               if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
+                                       args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
+                                       if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+                                               args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
+                                       if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
+                                               args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
+                               }
+                       } else {
+                               if (dig->linkb)
+                                       args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
+                               if (radeon_encoder->pixel_clock > 165000)
+                                       args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+                       }
+                       break;
+               default:
+                       DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+                       break;
+               }
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               break;
+       }
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+int
+atombios_get_encoder_mode(struct drm_encoder *encoder)
+{
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct drm_connector *connector;
+       struct radeon_connector *radeon_connector;
+       struct radeon_connector_atom_dig *dig_connector;
+
+       /* dp bridges are always DP */
+       if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
+               return ATOM_ENCODER_MODE_DP;
+
+       /* DVO is always DVO */
+       if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
+               return ATOM_ENCODER_MODE_DVO;
+
+       connector = radeon_get_connector_for_encoder(encoder);
+       /* if we don't have an active device yet, just use one of
+        * the connectors tied to the encoder.
+        */
+       if (!connector)
+               connector = radeon_get_connector_for_encoder_init(encoder);
+       radeon_connector = to_radeon_connector(connector);
+
+       switch (connector->connector_type) {
+       case DRM_MODE_CONNECTOR_DVII:
+       case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
+               if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+                       /* fix me */
+                       if (ASIC_IS_DCE4(rdev))
+                               return ATOM_ENCODER_MODE_DVI;
+                       else
+                               return ATOM_ENCODER_MODE_HDMI;
+               } else if (radeon_connector->use_digital)
+                       return ATOM_ENCODER_MODE_DVI;
+               else
+                       return ATOM_ENCODER_MODE_CRT;
+               break;
+       case DRM_MODE_CONNECTOR_DVID:
+       case DRM_MODE_CONNECTOR_HDMIA:
+       default:
+               if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+                       /* fix me */
+                       if (ASIC_IS_DCE4(rdev))
+                               return ATOM_ENCODER_MODE_DVI;
+                       else
+                               return ATOM_ENCODER_MODE_HDMI;
+               } else
+                       return ATOM_ENCODER_MODE_DVI;
+               break;
+       case DRM_MODE_CONNECTOR_LVDS:
+               return ATOM_ENCODER_MODE_LVDS;
+               break;
+       case DRM_MODE_CONNECTOR_DisplayPort:
+               dig_connector = radeon_connector->con_priv;
+               if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+                   (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+                       return ATOM_ENCODER_MODE_DP;
+               else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+                       /* fix me */
+                       if (ASIC_IS_DCE4(rdev))
+                               return ATOM_ENCODER_MODE_DVI;
+                       else
+                               return ATOM_ENCODER_MODE_HDMI;
+               } else
+                       return ATOM_ENCODER_MODE_DVI;
+               break;
+       case DRM_MODE_CONNECTOR_eDP:
+               return ATOM_ENCODER_MODE_DP;
+       case DRM_MODE_CONNECTOR_DVIA:
+       case DRM_MODE_CONNECTOR_VGA:
+               return ATOM_ENCODER_MODE_CRT;
+               break;
+       case DRM_MODE_CONNECTOR_Composite:
+       case DRM_MODE_CONNECTOR_SVIDEO:
+       case DRM_MODE_CONNECTOR_9PinDIN:
+               /* fix me */
+               return ATOM_ENCODER_MODE_TV;
+               /*return ATOM_ENCODER_MODE_CV;*/
+               break;
+       }
+}
+
+/*
+ * DIG Encoder/Transmitter Setup
+ *
+ * DCE 3.0/3.1
+ * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
+ * Supports up to 3 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1 can drive UNIPHY link A or link B
+ * DIG2 can drive UNIPHY link B or LVTMA
+ *
+ * DCE 3.2
+ * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
+ * Supports up to 5 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B
+ *
+ * DCE 4.0/5.0
+ * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
+ * Supports up to 6 digital outputs
+ * - 6 DIG encoder blocks.
+ * - DIG to PHY mapping is hardcoded
+ * DIG1 drives UNIPHY0 link A, A+B
+ * DIG2 drives UNIPHY0 link B
+ * DIG3 drives UNIPHY1 link A, A+B
+ * DIG4 drives UNIPHY1 link B
+ * DIG5 drives UNIPHY2 link A, A+B
+ * DIG6 drives UNIPHY2 link B
+ *
+ * DCE 4.1
+ * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
+ * Supports up to 6 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B
+ *
+ * Routing
+ * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
+ * Examples:
+ * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
+ * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
+ * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
+ * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
+ */
+
+union dig_encoder_control {
+       DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
+       DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
+       DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
+       DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
+};
+
+void
+atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_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_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+       union dig_encoder_control args;
+       int index = 0;
+       uint8_t frev, crev;
+       int dp_clock = 0;
+       int dp_lane_count = 0;
+       int hpd_id = RADEON_HPD_NONE;
+       int bpc = 8;
+
+       if (connector) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               struct radeon_connector_atom_dig *dig_connector =
+                       radeon_connector->con_priv;
+
+               dp_clock = dig_connector->dp_clock;
+               dp_lane_count = dig_connector->dp_lane_count;
+               hpd_id = radeon_connector->hpd.hpd;
+               bpc = connector->display_info.bpc;
+       }
+
+       /* no dig encoder assigned */
+       if (dig->dig_encoder == -1)
+               return;
+
+       memset(&args, 0, sizeof(args));
+
+       if (ASIC_IS_DCE4(rdev))
+               index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
+       else {
+               if (dig->dig_encoder)
+                       index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
+               else
+                       index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+       }
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (frev) {
+       case 1:
+               switch (crev) {
+               case 1:
+                       args.v1.ucAction = action;
+                       args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+                               args.v3.ucPanelMode = panel_mode;
+                       else
+                               args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+                       if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+                               args.v1.ucLaneNum = dp_lane_count;
+                       else if (radeon_encoder->pixel_clock > 165000)
+                               args.v1.ucLaneNum = 8;
+                       else
+                               args.v1.ucLaneNum = 4;
+
+                       if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
+                               args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+                       switch (radeon_encoder->encoder_id) {
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+                               args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+                               args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+                               args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
+                               break;
+                       }
+                       if (dig->linkb)
+                               args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
+                       else
+                               args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
+                       break;
+               case 2:
+               case 3:
+                       args.v3.ucAction = action;
+                       args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+                               args.v3.ucPanelMode = panel_mode;
+                       else
+                               args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+                       if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+                               args.v3.ucLaneNum = dp_lane_count;
+                       else if (radeon_encoder->pixel_clock > 165000)
+                               args.v3.ucLaneNum = 8;
+                       else
+                               args.v3.ucLaneNum = 4;
+
+                       if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
+                               args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
+                       args.v3.acConfig.ucDigSel = dig->dig_encoder;
+                       switch (bpc) {
+                       case 0:
+                               args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
+                               break;
+                       case 6:
+                               args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+                               break;
+                       case 8:
+                       default:
+                               args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+                               break;
+                       case 10:
+                               args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+                               break;
+                       case 12:
+                               args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+                               break;
+                       case 16:
+                               args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+                               break;
+                       }
+                       break;
+               case 4:
+                       args.v4.ucAction = action;
+                       args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+                               args.v4.ucPanelMode = panel_mode;
+                       else
+                               args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+                       if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+                               args.v4.ucLaneNum = dp_lane_count;
+                       else if (radeon_encoder->pixel_clock > 165000)
+                               args.v4.ucLaneNum = 8;
+                       else
+                               args.v4.ucLaneNum = 4;
+
+                       if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) {
+                               if (dp_clock == 270000)
+                                       args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
+                               else if (dp_clock == 540000)
+                                       args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
+                       }
+                       args.v4.acConfig.ucDigSel = dig->dig_encoder;
+                       switch (bpc) {
+                       case 0:
+                               args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
+                               break;
+                       case 6:
+                               args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+                               break;
+                       case 8:
+                       default:
+                               args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+                               break;
+                       case 10:
+                               args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+                               break;
+                       case 12:
+                               args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+                               break;
+                       case 16:
+                               args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+                               break;
+                       }
+                       if (hpd_id == RADEON_HPD_NONE)
+                               args.v4.ucHPD_ID = 0;
+                       else
+                               args.v4.ucHPD_ID = hpd_id + 1;
+                       break;
+               default:
+                       DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+                       break;
+               }
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               break;
+       }
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+union dig_transmitter_control {
+       DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
+       DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
+       DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
+       DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
+};
+
+void
+atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+       struct drm_connector *connector;
+       union dig_transmitter_control args;
+       int index = 0;
+       uint8_t frev, crev;
+       bool is_dp = false;
+       int pll_id = 0;
+       int dp_clock = 0;
+       int dp_lane_count = 0;
+       int connector_object_id = 0;
+       int igp_lane_info = 0;
+       int dig_encoder = dig->dig_encoder;
+
+       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+               connector = radeon_get_connector_for_encoder_init(encoder);
+               /* just needed to avoid bailing in the encoder check.  the encoder
+                * isn't used for init
+                */
+               dig_encoder = 0;
+       } else
+               connector = radeon_get_connector_for_encoder(encoder);
+
+       if (connector) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               struct radeon_connector_atom_dig *dig_connector =
+                       radeon_connector->con_priv;
+
+               dp_clock = dig_connector->dp_clock;
+               dp_lane_count = dig_connector->dp_lane_count;
+               connector_object_id =
+                       (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+               igp_lane_info = dig_connector->igp_lane_info;
+       }
+
+       if (encoder->crtc) {
+               struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+               pll_id = radeon_crtc->pll_id;
+       }
+
+       /* no dig encoder assigned */
+       if (dig_encoder == -1)
+               return;
+
+       if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)))
+               is_dp = true;
+
+       memset(&args, 0, sizeof(args));
+
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+               index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+               index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+               index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
+               break;
+       }
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (frev) {
+       case 1:
+               switch (crev) {
+               case 1:
+                       args.v1.ucAction = action;
+                       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+                               args.v1.usInitInfo = cpu_to_le16(connector_object_id);
+                       } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+                               args.v1.asMode.ucLaneSel = lane_num;
+                               args.v1.asMode.ucLaneSet = lane_set;
+                       } else {
+                               if (is_dp)
+                                       args.v1.usPixelClock =
+                                               cpu_to_le16(dp_clock / 10);
+                               else if (radeon_encoder->pixel_clock > 165000)
+                                       args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+                               else
+                                       args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       }
+
+                       args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
+
+                       if (dig_encoder)
+                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
+                       else
+                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
+
+                       if ((rdev->flags & RADEON_IS_IGP) &&
+                           (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
+                               if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
+                                       if (igp_lane_info & 0x1)
+                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+                                       else if (igp_lane_info & 0x2)
+                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
+                                       else if (igp_lane_info & 0x4)
+                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
+                                       else if (igp_lane_info & 0x8)
+                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
+                               } else {
+                                       if (igp_lane_info & 0x3)
+                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
+                                       else if (igp_lane_info & 0xc)
+                                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
+                               }
+                       }
+
+                       if (dig->linkb)
+                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
+                       else
+                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
+
+                       if (is_dp)
+                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+                       else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+                               if (dig->coherent_mode)
+                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+                               if (radeon_encoder->pixel_clock > 165000)
+                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
+                       }
+                       break;
+               case 2:
+                       args.v2.ucAction = action;
+                       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+                               args.v2.usInitInfo = cpu_to_le16(connector_object_id);
+                       } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+                               args.v2.asMode.ucLaneSel = lane_num;
+                               args.v2.asMode.ucLaneSet = lane_set;
+                       } else {
+                               if (is_dp)
+                                       args.v2.usPixelClock =
+                                               cpu_to_le16(dp_clock / 10);
+                               else if (radeon_encoder->pixel_clock > 165000)
+                                       args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+                               else
+                                       args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       }
+
+                       args.v2.acConfig.ucEncoderSel = dig_encoder;
+                       if (dig->linkb)
+                               args.v2.acConfig.ucLinkSel = 1;
+
+                       switch (radeon_encoder->encoder_id) {
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+                               args.v2.acConfig.ucTransmitterSel = 0;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+                               args.v2.acConfig.ucTransmitterSel = 1;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+                               args.v2.acConfig.ucTransmitterSel = 2;
+                               break;
+                       }
+
+                       if (is_dp) {
+                               args.v2.acConfig.fCoherentMode = 1;
+                               args.v2.acConfig.fDPConnector = 1;
+                       } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+                               if (dig->coherent_mode)
+                                       args.v2.acConfig.fCoherentMode = 1;
+                               if (radeon_encoder->pixel_clock > 165000)
+                                       args.v2.acConfig.fDualLinkConnector = 1;
+                       }
+                       break;
+               case 3:
+                       args.v3.ucAction = action;
+                       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+                               args.v3.usInitInfo = cpu_to_le16(connector_object_id);
+                       } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+                               args.v3.asMode.ucLaneSel = lane_num;
+                               args.v3.asMode.ucLaneSet = lane_set;
+                       } else {
+                               if (is_dp)
+                                       args.v3.usPixelClock =
+                                               cpu_to_le16(dp_clock / 10);
+                               else if (radeon_encoder->pixel_clock > 165000)
+                                       args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+                               else
+                                       args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       }
+
+                       if (is_dp)
+                               args.v3.ucLaneNum = dp_lane_count;
+                       else if (radeon_encoder->pixel_clock > 165000)
+                               args.v3.ucLaneNum = 8;
+                       else
+                               args.v3.ucLaneNum = 4;
+
+                       if (dig->linkb)
+                               args.v3.acConfig.ucLinkSel = 1;
+                       if (dig_encoder & 1)
+                               args.v3.acConfig.ucEncoderSel = 1;
+
+                       /* Select the PLL for the PHY
+                        * DP PHY should be clocked from external src if there is
+                        * one.
+                        */
+                       /* On DCE4, if there is an external clock, it generates the DP ref clock */
+                       if (is_dp && rdev->clock.dp_extclk)
+                               args.v3.acConfig.ucRefClkSource = 2; /* external src */
+                       else
+                               args.v3.acConfig.ucRefClkSource = pll_id;
+
+                       switch (radeon_encoder->encoder_id) {
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+                               args.v3.acConfig.ucTransmitterSel = 0;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+                               args.v3.acConfig.ucTransmitterSel = 1;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+                               args.v3.acConfig.ucTransmitterSel = 2;
+                               break;
+                       }
+
+                       if (is_dp)
+                               args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
+                       else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+                               if (dig->coherent_mode)
+                                       args.v3.acConfig.fCoherentMode = 1;
+                               if (radeon_encoder->pixel_clock > 165000)
+                                       args.v3.acConfig.fDualLinkConnector = 1;
+                       }
+                       break;
+               case 4:
+                       args.v4.ucAction = action;
+                       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+                               args.v4.usInitInfo = cpu_to_le16(connector_object_id);
+                       } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+                               args.v4.asMode.ucLaneSel = lane_num;
+                               args.v4.asMode.ucLaneSet = lane_set;
+                       } else {
+                               if (is_dp)
+                                       args.v4.usPixelClock =
+                                               cpu_to_le16(dp_clock / 10);
+                               else if (radeon_encoder->pixel_clock > 165000)
+                                       args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+                               else
+                                       args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       }
+
+                       if (is_dp)
+                               args.v4.ucLaneNum = dp_lane_count;
+                       else if (radeon_encoder->pixel_clock > 165000)
+                               args.v4.ucLaneNum = 8;
+                       else
+                               args.v4.ucLaneNum = 4;
+
+                       if (dig->linkb)
+                               args.v4.acConfig.ucLinkSel = 1;
+                       if (dig_encoder & 1)
+                               args.v4.acConfig.ucEncoderSel = 1;
+
+                       /* Select the PLL for the PHY
+                        * DP PHY should be clocked from external src if there is
+                        * one.
+                        */
+                       /* On DCE5 DCPLL usually generates the DP ref clock */
+                       if (is_dp) {
+                               if (rdev->clock.dp_extclk)
+                                       args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
+                               else
+                                       args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
+                       } else
+                               args.v4.acConfig.ucRefClkSource = pll_id;
+
+                       switch (radeon_encoder->encoder_id) {
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+                               args.v4.acConfig.ucTransmitterSel = 0;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+                               args.v4.acConfig.ucTransmitterSel = 1;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+                               args.v4.acConfig.ucTransmitterSel = 2;
+                               break;
+                       }
+
+                       if (is_dp)
+                               args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
+                       else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+                               if (dig->coherent_mode)
+                                       args.v4.acConfig.fCoherentMode = 1;
+                               if (radeon_encoder->pixel_clock > 165000)
+                                       args.v4.acConfig.fDualLinkConnector = 1;
+                       }
+                       break;
+               default:
+                       DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+                       break;
+               }
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               break;
+       }
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+bool
+atombios_set_edp_panel_power(struct drm_connector *connector, int action)
+{
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct drm_device *dev = radeon_connector->base.dev;
+       struct radeon_device *rdev = dev->dev_private;
+       union dig_transmitter_control args;
+       int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+       uint8_t frev, crev;
+
+       if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+               goto done;
+
+       if (!ASIC_IS_DCE4(rdev))
+               goto done;
+
+       if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
+           (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
+               goto done;
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               goto done;
+
+       memset(&args, 0, sizeof(args));
+
+       args.v1.ucAction = action;
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+       /* wait for the panel to power up */
+       if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
+               int i;
+
+               for (i = 0; i < 300; i++) {
+                       if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
+                               return true;
+                       mdelay(1);
+               }
+               return false;
+       }
+done:
+       return true;
+}
+
+union external_encoder_control {
+       EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
+       EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
+};
+
+static void
+atombios_external_encoder_setup(struct drm_encoder *encoder,
+                               struct drm_encoder *ext_encoder,
+                               int action)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
+       union external_encoder_control args;
+       struct drm_connector *connector;
+       int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
+       u8 frev, crev;
+       int dp_clock = 0;
+       int dp_lane_count = 0;
+       int connector_object_id = 0;
+       u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+       int bpc = 8;
+
+       if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
+               connector = radeon_get_connector_for_encoder_init(encoder);
+       else
+               connector = radeon_get_connector_for_encoder(encoder);
+
+       if (connector) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               struct radeon_connector_atom_dig *dig_connector =
+                       radeon_connector->con_priv;
+
+               dp_clock = dig_connector->dp_clock;
+               dp_lane_count = dig_connector->dp_lane_count;
+               connector_object_id =
+                       (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+               bpc = connector->display_info.bpc;
+       }
+
+       memset(&args, 0, sizeof(args));
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (frev) {
+       case 1:
+               /* no params on frev 1 */
+               break;
+       case 2:
+               switch (crev) {
+               case 1:
+               case 2:
+                       args.v1.sDigEncoder.ucAction = action;
+                       args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+                       if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) {
+                               if (dp_clock == 270000)
+                                       args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+                               args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
+                       } else if (radeon_encoder->pixel_clock > 165000)
+                               args.v1.sDigEncoder.ucLaneNum = 8;
+                       else
+                               args.v1.sDigEncoder.ucLaneNum = 4;
+                       break;
+               case 3:
+                       args.v3.sExtEncoder.ucAction = action;
+                       if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
+                               args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
+                       else
+                               args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+                       args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+                       if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
+                               if (dp_clock == 270000)
+                                       args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
+                               else if (dp_clock == 540000)
+                                       args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
+                               args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
+                       } else if (radeon_encoder->pixel_clock > 165000)
+                               args.v3.sExtEncoder.ucLaneNum = 8;
+                       else
+                               args.v3.sExtEncoder.ucLaneNum = 4;
+                       switch (ext_enum) {
+                       case GRAPH_OBJECT_ENUM_ID1:
+                               args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
+                               break;
+                       case GRAPH_OBJECT_ENUM_ID2:
+                               args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
+                               break;
+                       case GRAPH_OBJECT_ENUM_ID3:
+                               args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
+                               break;
+                       }
+                       switch (bpc) {
+                       case 0:
+                               args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE;
+                               break;
+                       case 6:
+                               args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+                               break;
+                       case 8:
+                       default:
+                               args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+                               break;
+                       case 10:
+                               args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+                               break;
+                       case 12:
+                               args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+                               break;
+                       case 16:
+                               args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+                               break;
+                       }
+                       break;
+               default:
+                       DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+                       return;
+               }
+               break;
+       default:
+               DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+               return;
+       }
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+static void
+atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
+{
+       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_YUV_PS_ALLOCATION args;
+       int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
+       uint32_t temp, reg;
+
+       memset(&args, 0, sizeof(args));
+
+       if (rdev->family >= CHIP_R600)
+               reg = R600_BIOS_3_SCRATCH;
+       else
+               reg = RADEON_BIOS_3_SCRATCH;
+
+       /* XXX: fix up scratch reg handling */
+       temp = RREG32(reg);
+       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+               WREG32(reg, (ATOM_S3_TV1_ACTIVE |
+                            (radeon_crtc->crtc_id << 18)));
+       else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+               WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
+       else
+               WREG32(reg, 0);
+
+       if (enable)
+               args.ucEnable = ATOM_ENABLE;
+       args.ucCRTC = radeon_crtc->crtc_id;
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+       WREG32(reg, temp);
+}
+
+static void
+radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
+       int index = 0;
+
+       memset(&args, 0, sizeof(args));
+
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+               index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+               index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+               index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+               else
+                       index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+                       index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+                       index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+               else
+                       index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+                       index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+                       index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+               else
+                       index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
+               break;
+       default:
+               return;
+       }
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               args.ucAction = ATOM_ENABLE;
+               /* workaround for DVOOutputControl on some RS690 systems */
+               if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
+                       u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
+                       WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       WREG32(RADEON_BIOS_3_SCRATCH, reg);
+               } else
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                       args.ucAction = ATOM_LCD_BLON;
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               }
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               args.ucAction = ATOM_DISABLE;
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                       args.ucAction = ATOM_LCD_BLOFF;
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               }
+               break;
+       }
+}
+
+static void
+radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+       struct radeon_connector *radeon_connector = NULL;
+       struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
+
+       if (connector) {
+               radeon_connector = to_radeon_connector(connector);
+               radeon_dig_connector = radeon_connector->con_priv;
+       }
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               /* some early dce3.2 boards have a bug in their transmitter control table */
+               if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+               else
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+                       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+                               atombios_set_edp_panel_power(connector,
+                                                            ATOM_TRANSMITTER_ACTION_POWER_ON);
+                               radeon_dig_connector->edp_on = true;
+                       }
+                       if (ASIC_IS_DCE4(rdev))
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+                       radeon_dp_link_train(encoder, connector);
+                       if (ASIC_IS_DCE4(rdev))
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
+               }
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+                       if (ASIC_IS_DCE4(rdev))
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+                       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+                               atombios_set_edp_panel_power(connector,
+                                                            ATOM_TRANSMITTER_ACTION_POWER_OFF);
+                               radeon_dig_connector->edp_on = false;
+                       }
+               }
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+               break;
+       }
+}
+
+static void
+radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
+                            struct drm_encoder *ext_encoder,
+                            int mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+       default:
+               if (ASIC_IS_DCE41(rdev)) {
+                       atombios_external_encoder_setup(encoder, ext_encoder,
+                                                       EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
+                       atombios_external_encoder_setup(encoder, ext_encoder,
+                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
+               } else
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               if (ASIC_IS_DCE41(rdev)) {
+                       atombios_external_encoder_setup(encoder, ext_encoder,
+                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
+                       atombios_external_encoder_setup(encoder, ext_encoder,
+                                                       EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
+               } else
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
+               break;
+       }
+}
+
+static void
+radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+       DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
+                 radeon_encoder->encoder_id, mode, radeon_encoder->devices,
+                 radeon_encoder->active_device);
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               radeon_atom_encoder_dpms_avivo(encoder, mode);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+               radeon_atom_encoder_dpms_dig(encoder, mode);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+               if (ASIC_IS_DCE5(rdev)) {
+                       switch (mode) {
+                       case DRM_MODE_DPMS_ON:
+                               atombios_dvo_setup(encoder, ATOM_ENABLE);
+                               break;
+                       case DRM_MODE_DPMS_STANDBY:
+                       case DRM_MODE_DPMS_SUSPEND:
+                       case DRM_MODE_DPMS_OFF:
+                               atombios_dvo_setup(encoder, ATOM_DISABLE);
+                               break;
+                       }
+               } else if (ASIC_IS_DCE3(rdev))
+                       radeon_atom_encoder_dpms_dig(encoder, mode);
+               else
+                       radeon_atom_encoder_dpms_avivo(encoder, mode);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+               if (ASIC_IS_DCE5(rdev)) {
+                       switch (mode) {
+                       case DRM_MODE_DPMS_ON:
+                               atombios_dac_setup(encoder, ATOM_ENABLE);
+                               break;
+                       case DRM_MODE_DPMS_STANDBY:
+                       case DRM_MODE_DPMS_SUSPEND:
+                       case DRM_MODE_DPMS_OFF:
+                               atombios_dac_setup(encoder, ATOM_DISABLE);
+                               break;
+                       }
+               } else
+                       radeon_atom_encoder_dpms_avivo(encoder, mode);
+               break;
+       default:
+               return;
+       }
+
+       if (ext_encoder)
+               radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
+
+       radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+}
+
+union crtc_source_param {
+       SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
+       SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
+};
+
+static void
+atombios_set_encoder_crtc_source(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);
+       union crtc_source_param args;
+       int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
+       uint8_t frev, crev;
+       struct radeon_encoder_atom_dig *dig;
+
+       memset(&args, 0, sizeof(args));
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (frev) {
+       case 1:
+               switch (crev) {
+               case 1:
+               default:
+                       if (ASIC_IS_AVIVO(rdev))
+                               args.v1.ucCRTC = radeon_crtc->crtc_id;
+                       else {
+                               if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
+                                       args.v1.ucCRTC = radeon_crtc->crtc_id;
+                               } else {
+                                       args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
+                               }
+                       }
+                       switch (radeon_encoder->encoder_id) {
+                       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+                               args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+                       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+                               if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
+                                       args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
+                               else
+                                       args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+                       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+                               args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+                               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+                                       args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
+                               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+                                       args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
+                               else
+                                       args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+                               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+                                       args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
+                               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+                                       args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
+                               else
+                                       args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
+                               break;
+                       }
+                       break;
+               case 2:
+                       args.v2.ucCRTC = radeon_crtc->crtc_id;
+                       if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
+                               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
+                               if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+                                       args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
+                               else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
+                                       args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
+                               else
+                                       args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
+                       } else
+                               args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
+                       switch (radeon_encoder->encoder_id) {
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+                               dig = radeon_encoder->enc_priv;
+                               switch (dig->dig_encoder) {
+                               case 0:
+                                       args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+                                       break;
+                               case 1:
+                                       args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+                                       break;
+                               case 2:
+                                       args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
+                                       break;
+                               case 3:
+                                       args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
+                                       break;
+                               case 4:
+                                       args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
+                                       break;
+                               case 5:
+                                       args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
+                                       break;
+                               }
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+                               args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+                               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+                                       args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+                               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+                                       args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+                               else
+                                       args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+                               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+                                       args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+                               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+                                       args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+                               else
+                                       args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
+                               break;
+                       }
+                       break;
+               }
+               break;
+       default:
+               DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+               return;
+       }
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+       /* update scratch regs with new routing */
+       radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+}
+
+static void
+atombios_apply_encoder_quirks(struct drm_encoder *encoder,
+                             struct drm_display_mode *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);
+
+       /* Funky macbooks */
+       if ((dev->pdev->device == 0x71C5) &&
+           (dev->pdev->subsystem_vendor == 0x106b) &&
+           (dev->pdev->subsystem_device == 0x0080)) {
+               if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
+                       uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
+
+                       lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
+                       lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
+
+                       WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
+               }
+       }
+
+       /* set scaler clears this on some chips */
+       if (ASIC_IS_AVIVO(rdev) &&
+           (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
+               if (ASIC_IS_DCE4(rdev)) {
+                       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+                               WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
+                                      EVERGREEN_INTERLEAVE_EN);
+                       else
+                               WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
+               } else {
+                       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+                               WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
+                                      AVIVO_D1MODE_INTERLEAVE_EN);
+                       else
+                               WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
+               }
+       }
+}
+
+static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_encoder *test_encoder;
+       struct radeon_encoder_atom_dig *dig;
+       uint32_t dig_enc_in_use = 0;
+
+       /* DCE4/5 */
+       if (ASIC_IS_DCE4(rdev)) {
+               dig = radeon_encoder->enc_priv;
+               if (ASIC_IS_DCE41(rdev)) {
+                       /* ontario follows DCE4 */
+                       if (rdev->family == CHIP_PALM) {
+                               if (dig->linkb)
+                                       return 1;
+                               else
+                                       return 0;
+                       } else
+                               /* llano follows DCE3.2 */
+                               return radeon_crtc->crtc_id;
+               } else {
+                       switch (radeon_encoder->encoder_id) {
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+                               if (dig->linkb)
+                                       return 1;
+                               else
+                                       return 0;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+                               if (dig->linkb)
+                                       return 3;
+                               else
+                                       return 2;
+                               break;
+                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+                               if (dig->linkb)
+                                       return 5;
+                               else
+                                       return 4;
+                               break;
+                       }
+               }
+       }
+
+       /* on DCE32 and encoder can driver any block so just crtc id */
+       if (ASIC_IS_DCE32(rdev)) {
+               return radeon_crtc->crtc_id;
+       }
+
+       /* on DCE3 - LVTMA can only be driven by DIGB */
+       list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
+               struct radeon_encoder *radeon_test_encoder;
+
+               if (encoder == test_encoder)
+                       continue;
+
+               if (!radeon_encoder_is_digital(test_encoder))
+                       continue;
+
+               radeon_test_encoder = to_radeon_encoder(test_encoder);
+               dig = radeon_test_encoder->enc_priv;
+
+               if (dig->dig_encoder >= 0)
+                       dig_enc_in_use |= (1 << dig->dig_encoder);
+       }
+
+       if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
+               if (dig_enc_in_use & 0x2)
+                       DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
+               return 1;
+       }
+       if (!(dig_enc_in_use & 1))
+               return 0;
+       return 1;
+}
+
+/* This only needs to be called once at startup */
+void
+radeon_atom_encoder_init(struct radeon_device *rdev)
+{
+       struct drm_device *dev = rdev->ddev;
+       struct drm_encoder *encoder;
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+               struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+               switch (radeon_encoder->encoder_id) {
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
+                       break;
+               default:
+                       break;
+               }
+
+               if (ext_encoder && ASIC_IS_DCE41(rdev))
+                       atombios_external_encoder_setup(encoder, ext_encoder,
+                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
+       }
+}
+
+static void
+radeon_atom_encoder_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);
+       struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+       radeon_encoder->pixel_clock = adjusted_mode->clock;
+
+       if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
+               if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
+                       atombios_yuv_setup(encoder, true);
+               else
+                       atombios_yuv_setup(encoder, false);
+       }
+
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+               atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+               if (ASIC_IS_DCE4(rdev)) {
+                       /* disable the transmitter */
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+                       /* setup and enable the encoder */
+                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+
+                       /* enable the transmitter */
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+               } else {
+                       /* disable the encoder and transmitter */
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+                       atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
+
+                       /* setup and enable the encoder and transmitter */
+                       atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+               }
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+               atombios_dvo_setup(encoder, ATOM_ENABLE);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               atombios_dac_setup(encoder, ATOM_ENABLE);
+               if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
+                       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+                               atombios_tv_setup(encoder, ATOM_ENABLE);
+                       else
+                               atombios_tv_setup(encoder, ATOM_DISABLE);
+               }
+               break;
+       }
+
+       if (ext_encoder) {
+               if (ASIC_IS_DCE41(rdev))
+                       atombios_external_encoder_setup(encoder, ext_encoder,
+                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
+               else
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+       }
+
+       atombios_apply_encoder_quirks(encoder, adjusted_mode);
+
+       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
+               r600_hdmi_enable(encoder);
+               r600_hdmi_setmode(encoder, adjusted_mode);
+       }
+}
+
+static bool
+atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+       if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
+                                      ATOM_DEVICE_CV_SUPPORT |
+                                      ATOM_DEVICE_CRT_SUPPORT)) {
+               DAC_LOAD_DETECTION_PS_ALLOCATION args;
+               int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
+               uint8_t frev, crev;
+
+               memset(&args, 0, sizeof(args));
+
+               if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+                       return false;
+
+               args.sDacload.ucMisc = 0;
+
+               if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
+                   (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
+                       args.sDacload.ucDacType = ATOM_DAC_A;
+               else
+                       args.sDacload.ucDacType = ATOM_DAC_B;
+
+               if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
+                       args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
+               else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
+                       args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
+               else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+                       args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
+                       if (crev >= 3)
+                               args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
+               } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+                       args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
+                       if (crev >= 3)
+                               args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
+               }
+
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+               return true;
+       } else
+               return false;
+}
+
+static enum drm_connector_status
+radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       uint32_t bios_0_scratch;
+
+       if (!atombios_dac_load_detect(encoder, connector)) {
+               DRM_DEBUG_KMS("detect returned false \n");
+               return connector_status_unknown;
+       }
+
+       if (rdev->family >= CHIP_R600)
+               bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+       else
+               bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
+
+       DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
+       if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+               if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+               if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+               if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+               if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+                       return connector_status_connected; /* CTV */
+               else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+                       return connector_status_connected; /* STV */
+       }
+       return connector_status_disconnected;
+}
+
+static enum drm_connector_status
+radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+       u32 bios_0_scratch;
+
+       if (!ASIC_IS_DCE4(rdev))
+               return connector_status_unknown;
+
+       if (!ext_encoder)
+               return connector_status_unknown;
+
+       if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
+               return connector_status_unknown;
+
+       /* load detect on the dp bridge */
+       atombios_external_encoder_setup(encoder, ext_encoder,
+                                       EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
+
+       bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+
+       DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
+       if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+               if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+               if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+               if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+               if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+                       return connector_status_connected; /* CTV */
+               else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+                       return connector_status_connected; /* STV */
+       }
+       return connector_status_disconnected;
+}
+
+void
+radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
+{
+       struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+       if (ext_encoder)
+               /* ddc_setup on the dp bridge */
+               atombios_external_encoder_setup(encoder, ext_encoder,
+                                               EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
+
+}
+
+static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
+{
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
+       if ((radeon_encoder->active_device &
+            (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
+           (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
+            ENCODER_OBJECT_ID_NONE)) {
+               struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+               if (dig)
+                       dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
+       }
+
+       radeon_atom_output_lock(encoder, true);
+       radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+       if (connector) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+               /* select the clock/data port if it uses a router */
+               if (radeon_connector->router.cd_valid)
+                       radeon_router_select_cd_port(radeon_connector);
+
+               /* turn eDP panel on for mode set */
+               if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+                       atombios_set_edp_panel_power(connector,
+                                                    ATOM_TRANSMITTER_ACTION_POWER_ON);
+       }
+
+       /* this is needed for the pll/ss setup to work correctly in some cases */
+       atombios_set_encoder_crtc_source(encoder);
+}
+
+static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
+{
+       radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+       radeon_atom_output_lock(encoder, false);
+}
+
+static void radeon_atom_encoder_disable(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_encoder_atom_dig *dig;
+
+       /* check for pre-DCE3 cards with shared encoders;
+        * can't really use the links individually, so don't disable
+        * the encoder if it's in use by another connector
+        */
+       if (!ASIC_IS_DCE3(rdev)) {
+               struct drm_encoder *other_encoder;
+               struct radeon_encoder *other_radeon_encoder;
+
+               list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
+                       other_radeon_encoder = to_radeon_encoder(other_encoder);
+                       if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
+                           drm_helper_encoder_in_use(other_encoder))
+                               goto disable_done;
+               }
+       }
+
+       radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+               atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+               if (ASIC_IS_DCE4(rdev))
+                       /* disable the transmitter */
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+               else {
+                       /* disable the encoder and transmitter */
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+                       atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
+               }
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+               atombios_dvo_setup(encoder, ATOM_DISABLE);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               atombios_dac_setup(encoder, ATOM_DISABLE);
+               if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+                       atombios_tv_setup(encoder, ATOM_DISABLE);
+               break;
+       }
+
+disable_done:
+       if (radeon_encoder_is_digital(encoder)) {
+               if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
+                       r600_hdmi_disable(encoder);
+               dig = radeon_encoder->enc_priv;
+               dig->dig_encoder = -1;
+       }
+       radeon_encoder->active_device = 0;
+}
+
+/* these are handled by the primary encoders */
+static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
+{
+
+}
+
+static void radeon_atom_ext_commit(struct drm_encoder *encoder)
+{
+
+}
+
+static void
+radeon_atom_ext_mode_set(struct drm_encoder *encoder,
+                        struct drm_display_mode *mode,
+                        struct drm_display_mode *adjusted_mode)
+{
+
+}
+
+static void radeon_atom_ext_disable(struct drm_encoder *encoder)
+{
+
+}
+
+static void
+radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
+{
+
+}
+
+static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
+                                      struct drm_display_mode *mode,
+                                      struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
+       .dpms = radeon_atom_ext_dpms,
+       .mode_fixup = radeon_atom_ext_mode_fixup,
+       .prepare = radeon_atom_ext_prepare,
+       .mode_set = radeon_atom_ext_mode_set,
+       .commit = radeon_atom_ext_commit,
+       .disable = radeon_atom_ext_disable,
+       /* no detect for TMDS/LVDS yet */
+};
+
+static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
+       .dpms = radeon_atom_encoder_dpms,
+       .mode_fixup = radeon_atom_mode_fixup,
+       .prepare = radeon_atom_encoder_prepare,
+       .mode_set = radeon_atom_encoder_mode_set,
+       .commit = radeon_atom_encoder_commit,
+       .disable = radeon_atom_encoder_disable,
+       .detect = radeon_atom_dig_detect,
+};
+
+static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
+       .dpms = radeon_atom_encoder_dpms,
+       .mode_fixup = radeon_atom_mode_fixup,
+       .prepare = radeon_atom_encoder_prepare,
+       .mode_set = radeon_atom_encoder_mode_set,
+       .commit = radeon_atom_encoder_commit,
+       .detect = radeon_atom_dac_detect,
+};
+
+void radeon_enc_destroy(struct drm_encoder *encoder)
+{
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       kfree(radeon_encoder->enc_priv);
+       drm_encoder_cleanup(encoder);
+       kfree(radeon_encoder);
+}
+
+static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
+       .destroy = radeon_enc_destroy,
+};
+
+struct radeon_encoder_atom_dac *
+radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
+{
+       struct drm_device *dev = radeon_encoder->base.dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
+
+       if (!dac)
+               return NULL;
+
+       dac->tv_std = radeon_atombios_get_tv_info(rdev);
+       return dac;
+}
+
+struct radeon_encoder_atom_dig *
+radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
+{
+       int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+       struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
+
+       if (!dig)
+               return NULL;
+
+       /* coherent mode by default */
+       dig->coherent_mode = true;
+       dig->dig_encoder = -1;
+
+       if (encoder_enum == 2)
+               dig->linkb = true;
+       else
+               dig->linkb = false;
+
+       return dig;
+}
+
+void
+radeon_add_atom_encoder(struct drm_device *dev,
+                       uint32_t encoder_enum,
+                       uint32_t supported_device,
+                       u16 caps)
+{
+       struct radeon_device *rdev = dev->dev_private;
+       struct drm_encoder *encoder;
+       struct radeon_encoder *radeon_encoder;
+
+       /* see if we already added it */
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               radeon_encoder = to_radeon_encoder(encoder);
+               if (radeon_encoder->encoder_enum == encoder_enum) {
+                       radeon_encoder->devices |= supported_device;
+                       return;
+               }
+
+       }
+
+       /* add a new one */
+       radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
+       if (!radeon_encoder)
+               return;
+
+       encoder = &radeon_encoder->base;
+       switch (rdev->num_crtc) {
+       case 1:
+               encoder->possible_crtcs = 0x1;
+               break;
+       case 2:
+       default:
+               encoder->possible_crtcs = 0x3;
+               break;
+       case 4:
+               encoder->possible_crtcs = 0xf;
+               break;
+       case 6:
+               encoder->possible_crtcs = 0x3f;
+               break;
+       }
+
+       radeon_encoder->enc_priv = NULL;
+
+       radeon_encoder->encoder_enum = encoder_enum;
+       radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+       radeon_encoder->devices = supported_device;
+       radeon_encoder->rmx_type = RMX_OFF;
+       radeon_encoder->underscan_type = UNDERSCAN_OFF;
+       radeon_encoder->is_ext_encoder = false;
+       radeon_encoder->caps = caps;
+
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                       radeon_encoder->rmx_type = RMX_FULL;
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+                       radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+               } else {
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+                       radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+               }
+               drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+               drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+               radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
+               drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
+               radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
+               drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                       radeon_encoder->rmx_type = RMX_FULL;
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+                       radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+               } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+                       radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+               } else {
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+                       radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+               }
+               drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
+               break;
+       case ENCODER_OBJECT_ID_SI170B:
+       case ENCODER_OBJECT_ID_CH7303:
+       case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
+       case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
+       case ENCODER_OBJECT_ID_TITFP513:
+       case ENCODER_OBJECT_ID_VT1623:
+       case ENCODER_OBJECT_ID_HDMI_SI1930:
+       case ENCODER_OBJECT_ID_TRAVIS:
+       case ENCODER_OBJECT_ID_NUTMEG:
+               /* these are handled by the primary encoders */
+               radeon_encoder->is_ext_encoder = true;
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+               else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+               else
+                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+               drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
+               break;
+       }
+}
index ed406e8404a3498870d517fd286b5824a8665e22..1d603a3335db65b4bf425228a8f98221d01fcd48 100644 (file)
@@ -157,6 +157,57 @@ int sumo_get_temp(struct radeon_device *rdev)
        return actual_temp * 1000;
 }
 
+void sumo_pm_init_profile(struct radeon_device *rdev)
+{
+       int idx;
+
+       /* default */
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
+
+       /* low,mid sh/mh */
+       if (rdev->flags & RADEON_IS_MOBILITY)
+               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+       else
+               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
+
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
+
+       /* high sh/mh */
+       idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx =
+               rdev->pm.power_state[idx].num_clock_modes - 1;
+
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx =
+               rdev->pm.power_state[idx].num_clock_modes - 1;
+}
+
 void evergreen_pm_misc(struct radeon_device *rdev)
 {
        int req_ps_idx = rdev->pm.requested_power_state_index;
@@ -353,6 +404,7 @@ void evergreen_hpd_init(struct radeon_device *rdev)
                default:
                        break;
                }
+               radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
        }
        if (rdev->irq.installed)
                evergreen_irq_set(rdev);
@@ -893,7 +945,7 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
        u32 tmp;
        int r;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
@@ -945,7 +997,6 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
 void evergreen_pcie_gart_disable(struct radeon_device *rdev)
 {
        u32 tmp;
-       int r;
 
        /* Disable all tables */
        WREG32(VM_CONTEXT0_CNTL, 0);
@@ -965,14 +1016,7 @@ void evergreen_pcie_gart_disable(struct radeon_device *rdev)
        WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
 }
 
 void evergreen_pcie_gart_fini(struct radeon_device *rdev)
@@ -1226,7 +1270,7 @@ void evergreen_mc_program(struct radeon_device *rdev)
                WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
                        rdev->mc.vram_end >> 12);
        }
-       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
        if (rdev->flags & RADEON_IS_IGP) {
                tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF;
                tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24;
@@ -3031,6 +3075,10 @@ static int evergreen_startup(struct radeon_device *rdev)
                }
        }
 
+       r = r600_vram_scratch_init(rdev);
+       if (r)
+               return r;
+
        evergreen_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                evergreen_agp_enable(rdev);
@@ -3235,6 +3283,7 @@ void evergreen_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        evergreen_pcie_gart_fini(rdev);
+       r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_agp_fini(rdev);
index dcf11bbc06d90d1f7762782d491820ad3f2b5c53..914e5af84163cc38b9e03e214af13db747b7dd80 100644 (file)
@@ -94,6 +94,15 @@ cp_set_surface_sync(struct radeon_device *rdev,
        else
                cp_coher_size = ((size + 255) >> 8);
 
+       if (rdev->family >= CHIP_CAYMAN) {
+               /* CP_COHER_CNTL2 has to be set manually when submitting a surface_sync
+                * to the RB directly. For IBs, the CP programs this as part of the
+                * surface_sync packet.
+                */
+               radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+               radeon_ring_write(rdev, (0x85e8 - PACKET3_SET_CONFIG_REG_START) >> 2);
+               radeon_ring_write(rdev, 0); /* CP_COHER_CNTL2 */
+       }
        radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
        radeon_ring_write(rdev, sync_type);
        radeon_ring_write(rdev, cp_coher_size);
@@ -174,7 +183,7 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
 static void
 set_tex_resource(struct radeon_device *rdev,
                 int format, int w, int h, int pitch,
-                u64 gpu_addr)
+                u64 gpu_addr, u32 size)
 {
        u32 sq_tex_resource_word0, sq_tex_resource_word1;
        u32 sq_tex_resource_word4, sq_tex_resource_word7;
@@ -196,6 +205,9 @@ set_tex_resource(struct radeon_device *rdev,
        sq_tex_resource_word7 = format |
                S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_TEXTURE);
 
+       cp_set_surface_sync(rdev,
+                           PACKET3_TC_ACTION_ENA, size, gpu_addr);
+
        radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8));
        radeon_ring_write(rdev, 0);
        radeon_ring_write(rdev, sq_tex_resource_word0);
@@ -613,11 +625,13 @@ int evergreen_blit_init(struct radeon_device *rdev)
        rdev->r600_blit.primitives.set_default_state = set_default_state;
 
        rdev->r600_blit.ring_size_common = 55; /* shaders + def state */
-       rdev->r600_blit.ring_size_common += 10; /* fence emit for VB IB */
+       rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
        rdev->r600_blit.ring_size_common += 5; /* done copy */
-       rdev->r600_blit.ring_size_common += 10; /* fence emit for done copy */
+       rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
 
        rdev->r600_blit.ring_size_per_loop = 74;
+       if (rdev->family >= CHIP_CAYMAN)
+               rdev->r600_blit.ring_size_per_loop += 9; /* additional DWs for surface sync */
 
        rdev->r600_blit.max_dim = 16384;
 
index 7fdfa8ea7570654b6d3faf70e410e5ff6b9554d7..38e1bda73d33be343058b1f63f9349ca7f80e3f1 100644 (file)
@@ -480,21 +480,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                }
                break;
        case DB_Z_INFO:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
-               if (r) {
-                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
-                                       "0x%04X\n", reg);
-                       return -EINVAL;
-               }
                track->db_z_info = radeon_get_ib_value(p, idx);
-               ib[idx] &= ~Z_ARRAY_MODE(0xf);
-               track->db_z_info &= ~Z_ARRAY_MODE(0xf);
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-                       ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-                       track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-               } else {
-                       ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-                       track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               if (!p->keep_tiling_flags) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                               "0x%04X\n", reg);
+                               return -EINVAL;
+                       }
+                       ib[idx] &= ~Z_ARRAY_MODE(0xf);
+                       track->db_z_info &= ~Z_ARRAY_MODE(0xf);
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                               ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                               track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       } else {
+                               ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       }
                }
                break;
        case DB_STENCIL_INFO:
@@ -607,40 +609,44 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR5_INFO:
        case CB_COLOR6_INFO:
        case CB_COLOR7_INFO:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
-               if (r) {
-                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
-                                       "0x%04X\n", reg);
-                       return -EINVAL;
-               }
                tmp = (reg - CB_COLOR0_INFO) / 0x3c;
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-                       ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-               } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-                       ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               if (!p->keep_tiling_flags) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                               "0x%04X\n", reg);
+                               return -EINVAL;
+                       }
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                               ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                               track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                               ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       }
                }
                break;
        case CB_COLOR8_INFO:
        case CB_COLOR9_INFO:
        case CB_COLOR10_INFO:
        case CB_COLOR11_INFO:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
-               if (r) {
-                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
-                                       "0x%04X\n", reg);
-                       return -EINVAL;
-               }
                tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-                       ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-               } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-                       ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               if (!p->keep_tiling_flags) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                               "0x%04X\n", reg);
+                               return -EINVAL;
+                       }
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                               ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                               track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                               ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       }
                }
                break;
        case CB_COLOR0_PITCH:
@@ -1311,10 +1317,12 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                                        return -EINVAL;
                                }
                                ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-                               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-                                       ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-                               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-                                       ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               if (!p->keep_tiling_flags) {
+                                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                                               ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                                               ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               }
                                texture = reloc->robj;
                                /* tex mip base */
                                r = evergreen_cs_packet_next_reloc(p, &reloc);
index fdb93f88457533046819ef1c0082994ad42d3954..0e579985746535d211d26bc1350bdf60e851bdb8 100644 (file)
@@ -262,8 +262,11 @@ int ni_mc_load_microcode(struct radeon_device *rdev)
                WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
 
                /* wait for training to complete */
-               while (!(RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD))
-                       udelay(10);
+               for (i = 0; i < rdev->usec_timeout; i++) {
+                       if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
+                               break;
+                       udelay(1);
+               }
 
                if (running)
                        WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
@@ -933,7 +936,7 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
@@ -978,8 +981,6 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev)
 
 void cayman_pcie_gart_disable(struct radeon_device *rdev)
 {
-       int r;
-
        /* Disable all tables */
        WREG32(VM_CONTEXT0_CNTL, 0);
        WREG32(VM_CONTEXT1_CNTL, 0);
@@ -995,14 +996,7 @@ void cayman_pcie_gart_disable(struct radeon_device *rdev)
        WREG32(VM_L2_CNTL2, 0);
        WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
               L2_CACHE_BIGK_FRAGMENT_SIZE(6));
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
 }
 
 void cayman_pcie_gart_fini(struct radeon_device *rdev)
@@ -1362,6 +1356,10 @@ static int cayman_startup(struct radeon_device *rdev)
                return r;
        }
 
+       r = r600_vram_scratch_init(rdev);
+       if (r)
+               return r;
+
        evergreen_mc_program(rdev);
        r = cayman_pcie_gart_enable(rdev);
        if (r)
@@ -1557,6 +1555,7 @@ void cayman_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        cayman_pcie_gart_fini(rdev);
+       r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);
index cbf49f4f408ed01b885e21741d08edb2b0ccfac3..ad158ea499015e1ceb8ca956c611d9f8944a133d 100644 (file)
@@ -537,6 +537,7 @@ void r100_hpd_init(struct radeon_device *rdev)
                default:
                        break;
                }
+               radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
        }
        if (rdev->irq.installed)
                r100_irq_set(rdev);
@@ -577,7 +578,7 @@ int r100_pci_gart_init(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.ram.ptr) {
+       if (rdev->gart.ptr) {
                WARN(1, "R100 PCI GART already initialized\n");
                return 0;
        }
@@ -636,10 +637,12 @@ void r100_pci_gart_disable(struct radeon_device *rdev)
 
 int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
+       u32 *gtt = rdev->gart.ptr;
+
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
        }
-       rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
+       gtt[i] = cpu_to_le32(lower_32_bits(addr));
        return 0;
 }
 
index 33f2b68c680b349a5d9e097776d329fc047a37ef..c93bc64707e1d6e3b59a5e2a7fe632b19e6efe99 100644 (file)
@@ -74,7 +74,7 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
 
 int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
-       void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+       void __iomem *ptr = rdev->gart.ptr;
 
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
@@ -93,7 +93,7 @@ int rv370_pcie_gart_init(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.vram.robj) {
+       if (rdev->gart.robj) {
                WARN(1, "RV370 PCIE GART already initialized\n");
                return 0;
        }
@@ -116,7 +116,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
        uint32_t tmp;
        int r;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
@@ -154,7 +154,6 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
 void rv370_pcie_gart_disable(struct radeon_device *rdev)
 {
        u32 tmp;
-       int r;
 
        WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0);
        WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0);
@@ -163,14 +162,7 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
        tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
        tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
        WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
 }
 
 void rv370_pcie_gart_fini(struct radeon_device *rdev)
@@ -709,16 +701,21 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                        return r;
                }
 
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-                       tile_flags |= R300_TXO_MACRO_TILE;
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-                       tile_flags |= R300_TXO_MICRO_TILE;
-               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-                       tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
-
-               tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
-               tmp |= tile_flags;
-               ib[idx] = tmp;
+               if (p->keep_tiling_flags) {
+                       ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */
+                                 ((idx_value & ~31) + (u32)reloc->lobj.gpu_offset);
+               } else {
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                               tile_flags |= R300_TXO_MACRO_TILE;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                               tile_flags |= R300_TXO_MICRO_TILE;
+                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+                               tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
+
+                       tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
+                       tmp |= tile_flags;
+                       ib[idx] = tmp;
+               }
                track->textures[i].robj = reloc->robj;
                track->tex_dirty = true;
                break;
@@ -768,24 +765,26 @@ 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 (!p->keep_tiling_flags) {
+                       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;
-               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-                       tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
+                       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;
+                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+                               tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
 
-               tmp = idx_value & ~(0x7 << 16);
-               tmp |= tile_flags;
-               ib[idx] = tmp;
+                       tmp = idx_value & ~(0x7 << 16);
+                       tmp |= tile_flags;
+                       ib[idx] = tmp;
+               }
                i = (reg - 0x4E38) >> 2;
                track->cb[i].pitch = idx_value & 0x3FFE;
                switch (((idx_value >> 21) & 0xF)) {
@@ -851,25 +850,26 @@ 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;
-               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-                       tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
+               if (!p->keep_tiling_flags) {
+                       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;
+                       }
 
-               tmp = idx_value & ~(0x7 << 16);
-               tmp |= tile_flags;
-               ib[idx] = tmp;
+                       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;
+                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+                               tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
 
+                       tmp = idx_value & ~(0x7 << 16);
+                       tmp |= tile_flags;
+                       ib[idx] = tmp;
+               }
                track->zb.pitch = idx_value & 0x3FFC;
                track->zb_dirty = true;
                break;
index 4e777c1e4b7b3401047f32ad23dcf3f49266c7d9..9cdda0b3b081e879f165f322e23780b338b583d9 100644 (file)
@@ -288,24 +288,6 @@ void r600_pm_get_dynpm_state(struct radeon_device *rdev)
                  pcie_lanes);
 }
 
-static int r600_pm_get_type_index(struct radeon_device *rdev,
-                                 enum radeon_pm_state_type ps_type,
-                                 int instance)
-{
-       int i;
-       int found_instance = -1;
-
-       for (i = 0; i < rdev->pm.num_power_states; i++) {
-               if (rdev->pm.power_state[i].type == ps_type) {
-                       found_instance++;
-                       if (found_instance == instance)
-                               return i;
-               }
-       }
-       /* return default if no match */
-       return rdev->pm.default_power_state_index;
-}
-
 void rs780_pm_init_profile(struct radeon_device *rdev)
 {
        if (rdev->pm.num_power_states == 2) {
@@ -421,6 +403,8 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
 
 void r600_pm_init_profile(struct radeon_device *rdev)
 {
+       int idx;
+
        if (rdev->family == CHIP_R600) {
                /* XXX */
                /* default */
@@ -502,81 +486,43 @@ void r600_pm_init_profile(struct radeon_device *rdev)
                        rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
                        rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
                        /* low sh */
-                       if (rdev->flags & RADEON_IS_MOBILITY) {
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
-                       } else {
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
-                       }
+                       if (rdev->flags & RADEON_IS_MOBILITY)
+                               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+                       else
+                               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
                        /* mid sh */
-                       if (rdev->flags & RADEON_IS_MOBILITY) {
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
-                       } else {
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
-                       }
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
                        /* high sh */
-                       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx =
-                               r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx =
-                               r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+                       idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+                       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
                        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
                        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
                        /* low mh */
-                       if (rdev->flags & RADEON_IS_MOBILITY) {
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
-                       } else {
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
-                       }
+                       if (rdev->flags & RADEON_IS_MOBILITY)
+                               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
+                       else
+                               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
                        /* mid mh */
-                       if (rdev->flags & RADEON_IS_MOBILITY) {
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
-                       } else {
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
-                       }
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
                        /* high mh */
-                       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx =
-                               r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx =
-                               r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+                       idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+                       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
                        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
                        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
                }
@@ -763,13 +709,14 @@ void r600_hpd_init(struct radeon_device *rdev)
        struct drm_device *dev = rdev->ddev;
        struct drm_connector *connector;
 
-       if (ASIC_IS_DCE3(rdev)) {
-               u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
-               if (ASIC_IS_DCE32(rdev))
-                       tmp |= DC_HPDx_EN;
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+               if (ASIC_IS_DCE3(rdev)) {
+                       u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
+                       if (ASIC_IS_DCE32(rdev))
+                               tmp |= DC_HPDx_EN;
 
-               list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                        switch (radeon_connector->hpd.hpd) {
                        case RADEON_HPD_1:
                                WREG32(DC_HPD1_CONTROL, tmp);
@@ -799,10 +746,7 @@ void r600_hpd_init(struct radeon_device *rdev)
                        default:
                                break;
                        }
-               }
-       } else {
-               list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               } else {
                        switch (radeon_connector->hpd.hpd) {
                        case RADEON_HPD_1:
                                WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN);
@@ -820,6 +764,7 @@ void r600_hpd_init(struct radeon_device *rdev)
                                break;
                        }
                }
+               radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
        }
        if (rdev->irq.installed)
                r600_irq_set(rdev);
@@ -897,7 +842,7 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
        /* flush hdp cache so updates hit vram */
        if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
            !(rdev->flags & RADEON_IS_AGP)) {
-               void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+               void __iomem *ptr = (void *)rdev->gart.ptr;
                u32 tmp;
 
                /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
@@ -932,7 +877,7 @@ int r600_pcie_gart_init(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.vram.robj) {
+       if (rdev->gart.robj) {
                WARN(1, "R600 PCIE GART already initialized\n");
                return 0;
        }
@@ -949,7 +894,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev)
        u32 tmp;
        int r, i;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
@@ -1004,7 +949,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev)
 void r600_pcie_gart_disable(struct radeon_device *rdev)
 {
        u32 tmp;
-       int i, r;
+       int i;
 
        /* Disable all tables */
        for (i = 0; i < 7; i++)
@@ -1031,14 +976,7 @@ void r600_pcie_gart_disable(struct radeon_device *rdev)
        WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
        WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
        WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
 }
 
 void r600_pcie_gart_fini(struct radeon_device *rdev)
@@ -1138,7 +1076,7 @@ static void r600_mc_program(struct radeon_device *rdev)
                WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
                WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12);
        }
-       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
        tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
        tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
        WREG32(MC_VM_FB_LOCATION, tmp);
@@ -1277,6 +1215,53 @@ int r600_mc_init(struct radeon_device *rdev)
        return 0;
 }
 
+int r600_vram_scratch_init(struct radeon_device *rdev)
+{
+       int r;
+
+       if (rdev->vram_scratch.robj == NULL) {
+               r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
+                                    PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+                                    &rdev->vram_scratch.robj);
+               if (r) {
+                       return r;
+               }
+       }
+
+       r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+       if (unlikely(r != 0))
+               return r;
+       r = radeon_bo_pin(rdev->vram_scratch.robj,
+                         RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr);
+       if (r) {
+               radeon_bo_unreserve(rdev->vram_scratch.robj);
+               return r;
+       }
+       r = radeon_bo_kmap(rdev->vram_scratch.robj,
+                               (void **)&rdev->vram_scratch.ptr);
+       if (r)
+               radeon_bo_unpin(rdev->vram_scratch.robj);
+       radeon_bo_unreserve(rdev->vram_scratch.robj);
+
+       return r;
+}
+
+void r600_vram_scratch_fini(struct radeon_device *rdev)
+{
+       int r;
+
+       if (rdev->vram_scratch.robj == NULL) {
+               return;
+       }
+       r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+       if (likely(r == 0)) {
+               radeon_bo_kunmap(rdev->vram_scratch.robj);
+               radeon_bo_unpin(rdev->vram_scratch.robj);
+               radeon_bo_unreserve(rdev->vram_scratch.robj);
+       }
+       radeon_bo_unref(&rdev->vram_scratch.robj);
+}
+
 /* We doesn't check that the GPU really needs a reset we simply do the
  * reset, it's up to the caller to determine if the GPU needs one. We
  * might add an helper function to check that.
@@ -2332,6 +2317,14 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
        if (rdev->wb.use_event) {
                u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET +
                        (u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base);
+               /* flush read cache over gart */
+               radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
+               radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
+                                       PACKET3_VC_ACTION_ENA |
+                                       PACKET3_SH_ACTION_ENA);
+               radeon_ring_write(rdev, 0xFFFFFFFF);
+               radeon_ring_write(rdev, 0);
+               radeon_ring_write(rdev, 10); /* poll interval */
                /* EVENT_WRITE_EOP - flush caches, send int */
                radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
                radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5));
@@ -2340,6 +2333,14 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
                radeon_ring_write(rdev, fence->seq);
                radeon_ring_write(rdev, 0);
        } else {
+               /* flush read cache over gart */
+               radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
+               radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
+                                       PACKET3_VC_ACTION_ENA |
+                                       PACKET3_SH_ACTION_ENA);
+               radeon_ring_write(rdev, 0xFFFFFFFF);
+               radeon_ring_write(rdev, 0);
+               radeon_ring_write(rdev, 10); /* poll interval */
                radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
                radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0));
                /* wait for 3D idle clean */
@@ -2421,6 +2422,10 @@ int r600_startup(struct radeon_device *rdev)
                }
        }
 
+       r = r600_vram_scratch_init(rdev);
+       if (r)
+               return r;
+
        r600_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                r600_agp_enable(rdev);
@@ -2641,6 +2646,7 @@ void r600_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        r600_pcie_gart_fini(rdev);
+       r600_vram_scratch_fini(rdev);
        radeon_agp_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
index c4cf1308d4a1e72ad7933bd0de0b091ea354a0f6..e09d2818f949f55615c8e33723f14d73bdb69660 100644 (file)
@@ -201,7 +201,7 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
 static void
 set_tex_resource(struct radeon_device *rdev,
                 int format, int w, int h, int pitch,
-                u64 gpu_addr)
+                u64 gpu_addr, u32 size)
 {
        uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
 
@@ -222,6 +222,9 @@ set_tex_resource(struct radeon_device *rdev,
                S_038010_DST_SEL_Z(SQ_SEL_Z) |
                S_038010_DST_SEL_W(SQ_SEL_W);
 
+       cp_set_surface_sync(rdev,
+                           PACKET3_TC_ACTION_ENA, size, gpu_addr);
+
        radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
        radeon_ring_write(rdev, 0);
        radeon_ring_write(rdev, sq_tex_resource_word0);
@@ -500,9 +503,9 @@ int r600_blit_init(struct radeon_device *rdev)
        rdev->r600_blit.primitives.set_default_state = set_default_state;
 
        rdev->r600_blit.ring_size_common = 40; /* shaders + def state */
-       rdev->r600_blit.ring_size_common += 10; /* fence emit for VB IB */
+       rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
        rdev->r600_blit.ring_size_common += 5; /* done copy */
-       rdev->r600_blit.ring_size_common += 10; /* fence emit for done copy */
+       rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
 
        rdev->r600_blit.ring_size_per_loop = 76;
        /* set_render_target emits 2 extra dwords on rv6xx */
@@ -760,10 +763,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
                vb[11] = i2f(h);
 
                rdev->r600_blit.primitives.set_tex_resource(rdev, FMT_8_8_8_8,
-                                                           w, h, w, src_gpu_addr);
-               rdev->r600_blit.primitives.cp_set_surface_sync(rdev,
-                                                              PACKET3_TC_ACTION_ENA,
-                                                              size_in_bytes, src_gpu_addr);
+                                                           w, h, w, src_gpu_addr, size_in_bytes);
                rdev->r600_blit.primitives.set_render_target(rdev, COLOR_8_8_8_8,
                                                             w, h, dst_gpu_addr);
                rdev->r600_blit.primitives.set_scissors(rdev, 0, 0, w, h);
index 0a2e023c15570ffdbd8c78280ac84123b6b17034..cb1acffd24303aca4c49b11e62b74719a527d51b 100644 (file)
@@ -941,7 +941,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_depth_control = radeon_get_ib_value(p, idx);
                break;
        case R_028010_DB_DEPTH_INFO:
-               if (r600_cs_packet_next_is_pkt3_nop(p)) {
+               if (!p->keep_tiling_flags &&
+                   r600_cs_packet_next_is_pkt3_nop(p)) {
                        r = r600_cs_packet_next_reloc(p, &reloc);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
@@ -992,7 +993,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_0280B4_CB_COLOR5_INFO:
        case R_0280B8_CB_COLOR6_INFO:
        case R_0280BC_CB_COLOR7_INFO:
-               if (r600_cs_packet_next_is_pkt3_nop(p)) {
+               if (!p->keep_tiling_flags &&
+                    r600_cs_packet_next_is_pkt3_nop(p)) {
                        r = r600_cs_packet_next_reloc(p, &reloc);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
@@ -1291,10 +1293,12 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
        mip_offset <<= 8;
 
        word0 = radeon_get_ib_value(p, idx + 0);
-       if (tiling_flags & RADEON_TILING_MACRO)
-               word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
-       else if (tiling_flags & RADEON_TILING_MICRO)
-               word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+       if (!p->keep_tiling_flags) {
+               if (tiling_flags & RADEON_TILING_MACRO)
+                       word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
+               else if (tiling_flags & RADEON_TILING_MICRO)
+                       word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+       }
        word1 = radeon_get_ib_value(p, idx + 1);
        w0 = G_038000_TEX_WIDTH(word0) + 1;
        h0 = G_038004_TEX_HEIGHT(word1) + 1;
@@ -1621,10 +1625,12 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                        return -EINVAL;
                                }
                                base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-                               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-                                       ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
-                               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-                                       ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+                               if (!p->keep_tiling_flags) {
+                                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                                               ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
+                                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                                               ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+                               }
                                texture = reloc->robj;
                                /* tex mip base */
                                r = r600_cs_packet_next_reloc(p, &reloc);
index e3170c794c1d98ba58fcc02cb6a94e8d2cf4533c..8227e76b5c70a1d1b97bcac741f1559272a2250e 100644 (file)
@@ -93,6 +93,7 @@ extern int radeon_audio;
 extern int radeon_disp_priority;
 extern int radeon_hw_i2c;
 extern int radeon_pcie_gen2;
+extern int radeon_msi;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -306,30 +307,17 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv,
  */
 struct radeon_mc;
 
-struct radeon_gart_table_ram {
-       volatile uint32_t               *ptr;
-};
-
-struct radeon_gart_table_vram {
-       struct radeon_bo                *robj;
-       volatile uint32_t               *ptr;
-};
-
-union radeon_gart_table {
-       struct radeon_gart_table_ram    ram;
-       struct radeon_gart_table_vram   vram;
-};
-
 #define RADEON_GPU_PAGE_SIZE 4096
 #define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1)
 #define RADEON_GPU_PAGE_SHIFT 12
 
 struct radeon_gart {
        dma_addr_t                      table_addr;
+       struct radeon_bo                *robj;
+       void                            *ptr;
        unsigned                        num_gpu_pages;
        unsigned                        num_cpu_pages;
        unsigned                        table_size;
-       union radeon_gart_table         table;
        struct page                     **pages;
        dma_addr_t                      *pages_addr;
        bool                            *ttm_alloced;
@@ -340,6 +328,8 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev);
 void radeon_gart_table_ram_free(struct radeon_device *rdev);
 int radeon_gart_table_vram_alloc(struct radeon_device *rdev);
 void radeon_gart_table_vram_free(struct radeon_device *rdev);
+int radeon_gart_table_vram_pin(struct radeon_device *rdev);
+void radeon_gart_table_vram_unpin(struct radeon_device *rdev);
 int radeon_gart_init(struct radeon_device *rdev);
 void radeon_gart_fini(struct radeon_device *rdev);
 void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
@@ -347,6 +337,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
                     int pages, struct page **pagelist,
                     dma_addr_t *dma_addr);
+void radeon_gart_restore(struct radeon_device *rdev);
 
 
 /*
@@ -437,25 +428,26 @@ union radeon_irq_stat_regs {
        struct evergreen_irq_stat_regs evergreen;
 };
 
+#define RADEON_MAX_HPD_PINS 6
+#define RADEON_MAX_CRTCS 6
+#define RADEON_MAX_HDMI_BLOCKS 2
+
 struct radeon_irq {
        bool            installed;
        bool            sw_int;
-       /* FIXME: use a define max crtc rather than hardcode it */
-       bool            crtc_vblank_int[6];
-       bool            pflip[6];
+       bool            crtc_vblank_int[RADEON_MAX_CRTCS];
+       bool            pflip[RADEON_MAX_CRTCS];
        wait_queue_head_t       vblank_queue;
-       /* FIXME: use defines for max hpd/dacs */
-       bool            hpd[6];
+       bool            hpd[RADEON_MAX_HPD_PINS];
        bool            gui_idle;
        bool            gui_idle_acked;
        wait_queue_head_t       idle_queue;
-       /* FIXME: use defines for max HDMI blocks */
-       bool            hdmi[2];
+       bool            hdmi[RADEON_MAX_HDMI_BLOCKS];
        spinlock_t sw_lock;
        int sw_refcount;
        union radeon_irq_stat_regs stat_regs;
-       spinlock_t pflip_lock[6];
-       int pflip_refcount[6];
+       spinlock_t pflip_lock[RADEON_MAX_CRTCS];
+       int pflip_refcount[RADEON_MAX_CRTCS];
 };
 
 int radeon_irq_kms_init(struct radeon_device *rdev);
@@ -533,7 +525,7 @@ struct r600_blit_cp_primitives {
        void (*set_vtx_resource)(struct radeon_device *rdev, u64 gpu_addr);
        void (*set_tex_resource)(struct radeon_device *rdev,
                                 int format, int w, int h, int pitch,
-                                u64 gpu_addr);
+                                u64 gpu_addr, u32 size);
        void (*set_scissors)(struct radeon_device *rdev, int x1, int y1,
                             int x2, int y2);
        void (*draw_auto)(struct radeon_device *rdev);
@@ -619,7 +611,8 @@ struct radeon_cs_parser {
        struct radeon_ib        *ib;
        void                    *track;
        unsigned                family;
-       int parser_error;
+       int                     parser_error;
+       bool                    keep_tiling_flags;
 };
 
 extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
@@ -792,8 +785,7 @@ struct radeon_pm_clock_info {
 
 struct radeon_power_state {
        enum radeon_pm_state_type type;
-       /* XXX: use a define for num clock modes */
-       struct radeon_pm_clock_info clock_info[8];
+       struct radeon_pm_clock_info *clock_info;
        /* number of valid clock modes in this power state */
        int num_clock_modes;
        struct radeon_pm_clock_info *default_clock_mode;
@@ -863,6 +855,9 @@ struct radeon_pm {
        struct device           *int_hwmon_dev;
 };
 
+int radeon_pm_get_type_index(struct radeon_device *rdev,
+                            enum radeon_pm_state_type ps_type,
+                            int instance);
 
 /*
  * Benchmarking
@@ -1143,12 +1138,55 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
 int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *filp);
 
-/* VRAM scratch page for HDP bug */
-struct r700_vram_scratch {
+/* VRAM scratch page for HDP bug, default vram page */
+struct r600_vram_scratch {
        struct radeon_bo                *robj;
        volatile uint32_t               *ptr;
+       u64                             gpu_addr;
 };
 
+
+/*
+ * Mutex which allows recursive locking from the same process.
+ */
+struct radeon_mutex {
+       struct mutex            mutex;
+       struct task_struct      *owner;
+       int                     level;
+};
+
+static inline void radeon_mutex_init(struct radeon_mutex *mutex)
+{
+       mutex_init(&mutex->mutex);
+       mutex->owner = NULL;
+       mutex->level = 0;
+}
+
+static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
+{
+       if (mutex_trylock(&mutex->mutex)) {
+               /* The mutex was unlocked before, so it's ours now */
+               mutex->owner = current;
+       } else if (mutex->owner != current) {
+               /* Another process locked the mutex, take it */
+               mutex_lock(&mutex->mutex);
+               mutex->owner = current;
+       }
+       /* Otherwise the mutex was already locked by this process */
+
+       mutex->level++;
+}
+
+static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
+{
+       if (--mutex->level > 0)
+               return;
+
+       mutex->owner = NULL;
+       mutex_unlock(&mutex->mutex);
+}
+
+
 /*
  * Core structure, functions and helpers.
  */
@@ -1204,7 +1242,7 @@ struct radeon_device {
        struct radeon_gem               gem;
        struct radeon_pm                pm;
        uint32_t                        bios_scratch[RADEON_BIOS_NUM_SCRATCH];
-       struct mutex                    cs_mutex;
+       struct radeon_mutex             cs_mutex;
        struct radeon_wb                wb;
        struct radeon_dummy_page        dummy_page;
        bool                            gpu_lockup;
@@ -1218,7 +1256,7 @@ struct radeon_device {
        const struct firmware *rlc_fw;  /* r6/700 RLC firmware */
        const struct firmware *mc_fw;   /* NI MC firmware */
        struct r600_blit r600_blit;
-       struct r700_vram_scratch vram_scratch;
+       struct r600_vram_scratch vram_scratch;
        int msi_enabled; /* msi enabled */
        struct r600_ih ih; /* r6/700 interrupt ring */
        struct work_struct hotplug_work;
@@ -1442,8 +1480,6 @@ void radeon_ring_write(struct radeon_device *rdev, uint32_t v);
 /* AGP */
 extern int radeon_gpu_reset(struct radeon_device *rdev);
 extern void radeon_agp_disable(struct radeon_device *rdev);
-extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
-extern void radeon_gart_restore(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
 extern bool radeon_card_posted(struct radeon_device *rdev);
@@ -1466,6 +1502,12 @@ extern int radeon_resume_kms(struct drm_device *dev);
 extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
 extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
 
+/*
+ * R600 vram scratch functions
+ */
+int r600_vram_scratch_init(struct radeon_device *rdev);
+void r600_vram_scratch_fini(struct radeon_device *rdev);
+
 /*
  * r600 functions used by radeon_encoder.c
  */
index e2944566ffea5a6942cfb0ab17c89316cacc49a1..a2e1eae114ef9ec1048e8b455bd5dee29fe28277 100644 (file)
@@ -834,7 +834,7 @@ static struct radeon_asic sumo_asic = {
        .pm_misc = &evergreen_pm_misc,
        .pm_prepare = &evergreen_pm_prepare,
        .pm_finish = &evergreen_pm_finish,
-       .pm_init_profile = &rs780_pm_init_profile,
+       .pm_init_profile = &sumo_pm_init_profile,
        .pm_get_dynpm_state = &r600_pm_get_dynpm_state,
        .pre_page_flip = &evergreen_pre_page_flip,
        .page_flip = &evergreen_page_flip,
index 85f14f0337e402f8d978cf7219e9861ef276aa5c..59914842a7292c63b5bad6032d3b1a496ed06e7d 100644 (file)
@@ -413,6 +413,7 @@ extern int evergreen_cs_parse(struct radeon_cs_parser *p);
 extern void evergreen_pm_misc(struct radeon_device *rdev);
 extern void evergreen_pm_prepare(struct radeon_device *rdev);
 extern void evergreen_pm_finish(struct radeon_device *rdev);
+extern void sumo_pm_init_profile(struct radeon_device *rdev);
 extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc);
 extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);
index 08d0b94332e6f19c72babaedd8828e69444b4ea1..d24baf30efcb8e583ab38b0540fe508369e47423 100644 (file)
@@ -62,6 +62,87 @@ union atom_supported_devices {
        struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
 };
 
+static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev,
+                                         ATOM_GPIO_I2C_ASSIGMENT *gpio,
+                                         u8 index)
+{
+       /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */
+       if ((rdev->family == CHIP_R420) ||
+           (rdev->family == CHIP_R423) ||
+           (rdev->family == CHIP_RV410)) {
+               if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) ||
+                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) ||
+                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) {
+                       gpio->ucClkMaskShift = 0x19;
+                       gpio->ucDataMaskShift = 0x18;
+               }
+       }
+
+       /* some evergreen boards have bad data for this entry */
+       if (ASIC_IS_DCE4(rdev)) {
+               if ((index == 7) &&
+                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
+                   (gpio->sucI2cId.ucAccess == 0)) {
+                       gpio->sucI2cId.ucAccess = 0x97;
+                       gpio->ucDataMaskShift = 8;
+                       gpio->ucDataEnShift = 8;
+                       gpio->ucDataY_Shift = 8;
+                       gpio->ucDataA_Shift = 8;
+               }
+       }
+
+       /* some DCE3 boards have bad data for this entry */
+       if (ASIC_IS_DCE3(rdev)) {
+               if ((index == 4) &&
+                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
+                   (gpio->sucI2cId.ucAccess == 0x94))
+                       gpio->sucI2cId.ucAccess = 0x14;
+       }
+}
+
+static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
+{
+       struct radeon_i2c_bus_rec i2c;
+
+       memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
+
+       i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
+       i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
+       i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
+       i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
+       i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
+       i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
+       i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
+       i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
+       i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
+       i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
+       i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
+       i2c.en_data_mask = (1 << gpio->ucDataEnShift);
+       i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
+       i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
+       i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
+       i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
+
+       if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
+               i2c.hw_capable = true;
+       else
+               i2c.hw_capable = false;
+
+       if (gpio->sucI2cId.ucAccess == 0xa0)
+               i2c.mm_i2c = true;
+       else
+               i2c.mm_i2c = false;
+
+       i2c.i2c_id = gpio->sucI2cId.ucAccess;
+
+       if (i2c.mask_clk_reg)
+               i2c.valid = true;
+       else
+               i2c.valid = false;
+
+       return i2c;
+}
+
 static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
                                                               uint8_t id)
 {
@@ -85,59 +166,10 @@ static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rd
                for (i = 0; i < num_indices; i++) {
                        gpio = &i2c_info->asGPIO_Info[i];
 
-                       /* some evergreen boards have bad data for this entry */
-                       if (ASIC_IS_DCE4(rdev)) {
-                               if ((i == 7) &&
-                                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
-                                   (gpio->sucI2cId.ucAccess == 0)) {
-                                       gpio->sucI2cId.ucAccess = 0x97;
-                                       gpio->ucDataMaskShift = 8;
-                                       gpio->ucDataEnShift = 8;
-                                       gpio->ucDataY_Shift = 8;
-                                       gpio->ucDataA_Shift = 8;
-                               }
-                       }
-
-                       /* some DCE3 boards have bad data for this entry */
-                       if (ASIC_IS_DCE3(rdev)) {
-                               if ((i == 4) &&
-                                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
-                                   (gpio->sucI2cId.ucAccess == 0x94))
-                                       gpio->sucI2cId.ucAccess = 0x14;
-                       }
+                       radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
 
                        if (gpio->sucI2cId.ucAccess == id) {
-                               i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-                               i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-                               i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-                               i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-                               i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-                               i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-                               i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-                               i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-                               i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-                               i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-                               i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-                               i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-                               i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-                               i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-                               i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-                               i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
-
-                               if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-                                       i2c.hw_capable = true;
-                               else
-                                       i2c.hw_capable = false;
-
-                               if (gpio->sucI2cId.ucAccess == 0xa0)
-                                       i2c.mm_i2c = true;
-                               else
-                                       i2c.mm_i2c = false;
-
-                               i2c.i2c_id = gpio->sucI2cId.ucAccess;
-
-                               if (i2c.mask_clk_reg)
-                                       i2c.valid = true;
+                               i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
                                break;
                        }
                }
@@ -157,8 +189,6 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
        int i, num_indices;
        char stmp[32];
 
-       memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
-
        if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
                i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
 
@@ -167,60 +197,12 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
 
                for (i = 0; i < num_indices; i++) {
                        gpio = &i2c_info->asGPIO_Info[i];
-                       i2c.valid = false;
-
-                       /* some evergreen boards have bad data for this entry */
-                       if (ASIC_IS_DCE4(rdev)) {
-                               if ((i == 7) &&
-                                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
-                                   (gpio->sucI2cId.ucAccess == 0)) {
-                                       gpio->sucI2cId.ucAccess = 0x97;
-                                       gpio->ucDataMaskShift = 8;
-                                       gpio->ucDataEnShift = 8;
-                                       gpio->ucDataY_Shift = 8;
-                                       gpio->ucDataA_Shift = 8;
-                               }
-                       }
 
-                       /* some DCE3 boards have bad data for this entry */
-                       if (ASIC_IS_DCE3(rdev)) {
-                               if ((i == 4) &&
-                                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
-                                   (gpio->sucI2cId.ucAccess == 0x94))
-                                       gpio->sucI2cId.ucAccess = 0x14;
-                       }
+                       radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
 
-                       i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-                       i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-                       i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-                       i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-                       i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-                       i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-                       i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-                       i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-                       i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-                       i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-                       i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-                       i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-                       i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-                       i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-                       i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-                       i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
-
-                       if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-                               i2c.hw_capable = true;
-                       else
-                               i2c.hw_capable = false;
-
-                       if (gpio->sucI2cId.ucAccess == 0xa0)
-                               i2c.mm_i2c = true;
-                       else
-                               i2c.mm_i2c = false;
+                       i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
 
-                       i2c.i2c_id = gpio->sucI2cId.ucAccess;
-
-                       if (i2c.mask_clk_reg) {
-                               i2c.valid = true;
+                       if (i2c.valid) {
                                sprintf(stmp, "0x%x", i2c.i2c_id);
                                rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
                        }
@@ -1996,10 +1978,14 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
                return state_index;
        /* last mode is usually default, array is low to high */
        for (i = 0; i < num_modes; i++) {
+               rdev->pm.power_state[state_index].clock_info =
+                       kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+               if (!rdev->pm.power_state[state_index].clock_info)
+                       return state_index;
+               rdev->pm.power_state[state_index].num_clock_modes = 1;
                rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
                switch (frev) {
                case 1:
-                       rdev->pm.power_state[state_index].num_clock_modes = 1;
                        rdev->pm.power_state[state_index].clock_info[0].mclk =
                                le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
                        rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2035,7 +2021,6 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
                        state_index++;
                        break;
                case 2:
-                       rdev->pm.power_state[state_index].num_clock_modes = 1;
                        rdev->pm.power_state[state_index].clock_info[0].mclk =
                                le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
                        rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2072,7 +2057,6 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
                        state_index++;
                        break;
                case 3:
-                       rdev->pm.power_state[state_index].num_clock_modes = 1;
                        rdev->pm.power_state[state_index].clock_info[0].mclk =
                                le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
                        rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2257,7 +2241,7 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde
                rdev->pm.default_power_state_index = state_index;
                rdev->pm.power_state[state_index].default_clock_mode =
                        &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
-               if (ASIC_IS_DCE5(rdev)) {
+               if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
                        /* NI chips post without MC ucode, so default clocks are strobe mode only */
                        rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
                        rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
@@ -2377,17 +2361,31 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
                         le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
                         (power_state->v1.ucNonClockStateIndex *
                          power_info->pplib.ucNonClockSize));
-               for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
-                       clock_info = (union pplib_clock_info *)
-                               (mode_info->atom_context->bios + data_offset +
-                                le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
-                                (power_state->v1.ucClockStateIndices[j] *
-                                 power_info->pplib.ucClockInfoSize));
-                       valid = radeon_atombios_parse_pplib_clock_info(rdev,
-                                                                      state_index, mode_index,
-                                                                      clock_info);
-                       if (valid)
-                               mode_index++;
+               rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
+                                                            ((power_info->pplib.ucStateEntrySize - 1) ?
+                                                             (power_info->pplib.ucStateEntrySize - 1) : 1),
+                                                            GFP_KERNEL);
+               if (!rdev->pm.power_state[i].clock_info)
+                       return state_index;
+               if (power_info->pplib.ucStateEntrySize - 1) {
+                       for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
+                               clock_info = (union pplib_clock_info *)
+                                       (mode_info->atom_context->bios + data_offset +
+                                        le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
+                                        (power_state->v1.ucClockStateIndices[j] *
+                                         power_info->pplib.ucClockInfoSize));
+                               valid = radeon_atombios_parse_pplib_clock_info(rdev,
+                                                                              state_index, mode_index,
+                                                                              clock_info);
+                               if (valid)
+                                       mode_index++;
+                       }
+               } else {
+                       rdev->pm.power_state[state_index].clock_info[0].mclk =
+                               rdev->clock.default_mclk;
+                       rdev->pm.power_state[state_index].clock_info[0].sclk =
+                               rdev->clock.default_sclk;
+                       mode_index++;
                }
                rdev->pm.power_state[state_index].num_clock_modes = mode_index;
                if (mode_index) {
@@ -2456,18 +2454,32 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
                non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
                non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
                        &non_clock_info_array->nonClockInfo[non_clock_array_index];
-               for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
-                       clock_array_index = power_state->v2.clockInfoIndex[j];
-                       /* XXX this might be an inagua bug... */
-                       if (clock_array_index >= clock_info_array->ucNumEntries)
-                               continue;
-                       clock_info = (union pplib_clock_info *)
-                               &clock_info_array->clockInfo[clock_array_index];
-                       valid = radeon_atombios_parse_pplib_clock_info(rdev,
-                                                                      state_index, mode_index,
-                                                                      clock_info);
-                       if (valid)
-                               mode_index++;
+               rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
+                                                            (power_state->v2.ucNumDPMLevels ?
+                                                             power_state->v2.ucNumDPMLevels : 1),
+                                                            GFP_KERNEL);
+               if (!rdev->pm.power_state[i].clock_info)
+                       return state_index;
+               if (power_state->v2.ucNumDPMLevels) {
+                       for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
+                               clock_array_index = power_state->v2.clockInfoIndex[j];
+                               /* XXX this might be an inagua bug... */
+                               if (clock_array_index >= clock_info_array->ucNumEntries)
+                                       continue;
+                               clock_info = (union pplib_clock_info *)
+                                       &clock_info_array->clockInfo[clock_array_index];
+                               valid = radeon_atombios_parse_pplib_clock_info(rdev,
+                                                                              state_index, mode_index,
+                                                                              clock_info);
+                               if (valid)
+                                       mode_index++;
+                       }
+               } else {
+                       rdev->pm.power_state[state_index].clock_info[0].mclk =
+                               rdev->clock.default_mclk;
+                       rdev->pm.power_state[state_index].clock_info[0].sclk =
+                               rdev->clock.default_sclk;
+                       mode_index++;
                }
                rdev->pm.power_state[state_index].num_clock_modes = mode_index;
                if (mode_index) {
@@ -2524,19 +2536,23 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
        } else {
                rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
                if (rdev->pm.power_state) {
-                       /* add the default mode */
-                       rdev->pm.power_state[state_index].type =
-                               POWER_STATE_TYPE_DEFAULT;
-                       rdev->pm.power_state[state_index].num_clock_modes = 1;
-                       rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
-                       rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
-                       rdev->pm.power_state[state_index].default_clock_mode =
-                               &rdev->pm.power_state[state_index].clock_info[0];
-                       rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
-                       rdev->pm.power_state[state_index].pcie_lanes = 16;
-                       rdev->pm.default_power_state_index = state_index;
-                       rdev->pm.power_state[state_index].flags = 0;
-                       state_index++;
+                       rdev->pm.power_state[0].clock_info =
+                               kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+                       if (rdev->pm.power_state[0].clock_info) {
+                               /* add the default mode */
+                               rdev->pm.power_state[state_index].type =
+                                       POWER_STATE_TYPE_DEFAULT;
+                               rdev->pm.power_state[state_index].num_clock_modes = 1;
+                               rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
+                               rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
+                               rdev->pm.power_state[state_index].default_clock_mode =
+                                       &rdev->pm.power_state[state_index].clock_info[0];
+                               rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+                               rdev->pm.power_state[state_index].pcie_lanes = 16;
+                               rdev->pm.default_power_state_index = state_index;
+                               rdev->pm.power_state[state_index].flags = 0;
+                               state_index++;
+                       }
                }
        }
 
index 5cafc90de7f8cec757fa5695db9865ccc621cabc..17e1a9b2d8fbf3e1dedce2923a7e5b726aea284c 100644 (file)
@@ -98,7 +98,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
        struct radeon_bo *sobj = NULL;
        uint64_t saddr, daddr;
        int r, n;
-       unsigned int time;
+       int time;
 
        n = RADEON_BENCHMARK_ITERATIONS;
        r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj);
index 8bf83c4b4147541b0379f75dcec3e36177848dd1..81fc100be7e18c321c088bc787e1154de96e11e3 100644 (file)
@@ -2563,14 +2563,17 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
 
        /* allocate 2 power states */
        rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL);
-       if (!rdev->pm.power_state) {
-               rdev->pm.default_power_state_index = state_index;
-               rdev->pm.num_power_states = 0;
-
-               rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
-               rdev->pm.current_clock_mode_index = 0;
-               return;
-       }
+       if (rdev->pm.power_state) {
+               /* allocate 1 clock mode per state */
+               rdev->pm.power_state[0].clock_info =
+                       kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+               rdev->pm.power_state[1].clock_info =
+                       kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+               if (!rdev->pm.power_state[0].clock_info ||
+                   !rdev->pm.power_state[1].clock_info)
+                       goto pm_failed;
+       } else
+               goto pm_failed;
 
        /* check for a thermal chip */
        offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE);
@@ -2733,6 +2736,14 @@ default_mode:
        rdev->pm.default_power_state_index = state_index;
        rdev->pm.num_power_states = state_index + 1;
 
+       rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+       rdev->pm.current_clock_mode_index = 0;
+       return;
+
+pm_failed:
+       rdev->pm.default_power_state_index = state_index;
+       rdev->pm.num_power_states = 0;
+
        rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
        rdev->pm.current_clock_mode_index = 0;
 }
index dec6cbe6a0a6a4ef5a1b59be5b63e037521870a4..e7cb3ab09243165c57d261944cd30b489703e149 100644 (file)
@@ -44,8 +44,6 @@ extern void
 radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
                             struct drm_connector *drm_connector);
 
-bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
-
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
@@ -432,55 +430,6 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
        return 0;
 }
 
-/*
- * Some integrated ATI Radeon chipset implementations (e. g.
- * Asus M2A-VM HDMI) may indicate the availability of a DDC,
- * even when there's no monitor connected. For these connectors
- * following DDC probe extension will be applied: check also for the
- * availability of EDID with at least a correct EDID header. Only then,
- * DDC is assumed to be available. This prevents drm_get_edid() and
- * drm_edid_block_valid() from periodically dumping data and kernel
- * errors into the logs and onto the terminal.
- */
-static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
-                                    uint32_t supported_device,
-                                    int connector_type)
-{
-       /* Asus M2A-VM HDMI board sends data to i2c bus even,
-        * if HDMI add-on card is not plugged in or HDMI is disabled in
-        * BIOS. Valid DDC can only be assumed, if also a valid EDID header
-        * can be retrieved via i2c bus during DDC probe */
-       if ((dev->pdev->device == 0x791e) &&
-           (dev->pdev->subsystem_vendor == 0x1043) &&
-           (dev->pdev->subsystem_device == 0x826d)) {
-               if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
-                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-                       return true;
-       }
-       /* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
-        * for a DVI connector that is not implemented */
-       if ((dev->pdev->device == 0x796e) &&
-           (dev->pdev->subsystem_vendor == 0x1019) &&
-           (dev->pdev->subsystem_device == 0x2615)) {
-               if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
-                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-                       return true;
-       }
-       /* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100
-        * (RS690M) sends data to i2c bus for a HDMI connector that
-        * is not implemented */
-       if ((dev->pdev->device == 0x791f) &&
-           (dev->pdev->subsystem_vendor == 0x1179) &&
-           (dev->pdev->subsystem_device == 0xff68)) {
-               if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
-                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-                       return true;
-       }
-
-       /* Default: no EDID header probe required for DDC probing */
-       return false;
-}
-
 static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
                                          struct drm_connector *connector)
 {
@@ -721,8 +670,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
                ret = connector_status_disconnected;
 
        if (radeon_connector->ddc_bus)
-               dret = radeon_ddc_probe(radeon_connector,
-                                       radeon_connector->requires_extended_probe);
+               dret = radeon_ddc_probe(radeon_connector);
        if (dret) {
                radeon_connector->detected_by_load = false;
                if (radeon_connector->edid) {
@@ -764,7 +712,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
                if (radeon_connector->dac_load_detect && encoder) {
                        encoder_funcs = encoder->helper_private;
                        ret = encoder_funcs->detect(encoder, connector);
-                       if (ret == connector_status_connected)
+                       if (ret != connector_status_disconnected)
                                radeon_connector->detected_by_load = true;
                }
        }
@@ -904,8 +852,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
        bool dret = false;
 
        if (radeon_connector->ddc_bus)
-               dret = radeon_ddc_probe(radeon_connector,
-                                       radeon_connector->requires_extended_probe);
+               dret = radeon_ddc_probe(radeon_connector);
        if (dret) {
                radeon_connector->detected_by_load = false;
                if (radeon_connector->edid) {
@@ -1005,8 +952,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                                        ret = encoder_funcs->detect(encoder, connector);
                                        if (ret == connector_status_connected) {
                                                radeon_connector->use_digital = false;
-                                               radeon_connector->detected_by_load = true;
                                        }
+                                       if (ret != connector_status_disconnected)
+                                               radeon_connector->detected_by_load = true;
                                }
                                break;
                        }
@@ -1203,7 +1151,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
                }
        } else {
                /* need to setup ddc on the bridge */
-               if (radeon_connector_encoder_is_dp_bridge(connector)) {
+               if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
+                       ENCODER_OBJECT_ID_NONE) {
                        if (encoder)
                                radeon_atom_ext_encoder_setup_ddc(encoder);
                }
@@ -1213,13 +1162,12 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
        return ret;
 }
 
-bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector)
+u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
 {
        struct drm_mode_object *obj;
        struct drm_encoder *encoder;
        struct radeon_encoder *radeon_encoder;
        int i;
-       bool found = false;
 
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
                if (connector->encoder_ids[i] == 0)
@@ -1235,14 +1183,13 @@ bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector)
                switch (radeon_encoder->encoder_id) {
                case ENCODER_OBJECT_ID_TRAVIS:
                case ENCODER_OBJECT_ID_NUTMEG:
-                       found = true;
-                       break;
+                       return radeon_encoder->encoder_id;
                default:
                        break;
                }
        }
 
-       return found;
+       return ENCODER_OBJECT_ID_NONE;
 }
 
 bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
@@ -1319,7 +1266,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                if (!radeon_dig_connector->edp_on)
                        atombios_set_edp_panel_power(connector,
                                                     ATOM_TRANSMITTER_ACTION_POWER_OFF);
-       } else if (radeon_connector_encoder_is_dp_bridge(connector)) {
+       } else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
+                  ENCODER_OBJECT_ID_NONE) {
                /* DP bridges are always DP */
                radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
                /* get the DPCD from the bridge */
@@ -1328,8 +1276,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                if (encoder) {
                        /* setup ddc on the bridge */
                        radeon_atom_ext_encoder_setup_ddc(encoder);
-                       if (radeon_ddc_probe(radeon_connector,
-                                            radeon_connector->requires_extended_probe)) /* try DDC */
+                       if (radeon_ddc_probe(radeon_connector)) /* try DDC */
                                ret = connector_status_connected;
                        else if (radeon_connector->dac_load_detect) { /* try load detection */
                                struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
@@ -1347,8 +1294,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                                if (radeon_dp_getdpcd(radeon_connector))
                                        ret = connector_status_connected;
                        } else {
-                               if (radeon_ddc_probe(radeon_connector,
-                                                    radeon_connector->requires_extended_probe))
+                               if (radeon_ddc_probe(radeon_connector))
                                        ret = connector_status_connected;
                        }
                }
@@ -1493,9 +1439,7 @@ radeon_add_atom_connector(struct drm_device *dev,
        radeon_connector->shared_ddc = shared_ddc;
        radeon_connector->connector_object_id = connector_object_id;
        radeon_connector->hpd = *hpd;
-       radeon_connector->requires_extended_probe =
-               radeon_connector_needs_extended_probe(rdev, supported_device,
-                                                       connector_type);
+
        radeon_connector->router = *router;
        if (router->ddc_valid || router->cd_valid) {
                radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1842,9 +1786,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
        radeon_connector->devices = supported_device;
        radeon_connector->connector_object_id = connector_object_id;
        radeon_connector->hpd = *hpd;
-       radeon_connector->requires_extended_probe =
-               radeon_connector_needs_extended_probe(rdev, supported_device,
-                                                       connector_type);
+
        switch (connector_type) {
        case DRM_MODE_CONNECTOR_VGA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
index fae00c0d75aaf1fae7fcbfc9b504370f560f5d42..29afd71e0840a0b9995b5e30027577adeec45b92 100644 (file)
@@ -93,7 +93,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
 {
        struct drm_radeon_cs *cs = data;
        uint64_t *chunk_array_ptr;
-       unsigned size, i;
+       unsigned size, i, flags = 0;
 
        if (!cs->num_chunks) {
                return 0;
@@ -140,6 +140,10 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                        if (p->chunks[i].length_dw == 0)
                                return -EINVAL;
                }
+               if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS &&
+                   !p->chunks[i].length_dw) {
+                       return -EINVAL;
+               }
 
                p->chunks[i].length_dw = user_chunk.length_dw;
                p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data;
@@ -155,6 +159,9 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                                               p->chunks[i].user_ptr, size)) {
                                return -EFAULT;
                        }
+                       if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) {
+                               flags = p->chunks[i].kdata[0];
+                       }
                } else {
                        p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
                        p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -174,6 +181,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                          p->chunks[p->chunk_ib_idx].length_dw);
                return -EINVAL;
        }
+
+       p->keep_tiling_flags = (flags & RADEON_CS_KEEP_TILING_FLAGS) != 0;
        return 0;
 }
 
@@ -222,7 +231,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        struct radeon_cs_chunk *ib_chunk;
        int r;
 
-       mutex_lock(&rdev->cs_mutex);
+       radeon_mutex_lock(&rdev->cs_mutex);
        /* initialize parser */
        memset(&parser, 0, sizeof(struct radeon_cs_parser));
        parser.filp = filp;
@@ -233,14 +242,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        r =  radeon_ib_get(rdev, &parser.ib);
        if (r) {
                DRM_ERROR("Failed to get ib !\n");
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        r = radeon_cs_parser_relocs(&parser);
@@ -248,7 +257,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                if (r != -ERESTARTSYS)
                        DRM_ERROR("Failed to parse relocation %d!\n", r);
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        /* Copy the packet into the IB, the parser will read from the
@@ -260,14 +269,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        if (r || parser.parser_error) {
                DRM_ERROR("Invalid command stream !\n");
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        r = radeon_cs_finish_pages(&parser);
        if (r) {
                DRM_ERROR("Invalid command stream !\n");
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        r = radeon_ib_schedule(rdev, parser.ib);
@@ -275,7 +284,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                DRM_ERROR("Failed to schedule IB !\n");
        }
        radeon_cs_parser_fini(&parser, r);
-       mutex_unlock(&rdev->cs_mutex);
+       radeon_mutex_unlock(&rdev->cs_mutex);
        return r;
 }
 
index c33bc914d93df9fce399c09d69fb770708c90393..c4d00a171411890fe701ea853ca084c39e4ac3b7 100644 (file)
@@ -716,7 +716,7 @@ int radeon_device_init(struct radeon_device *rdev,
 
        /* mutex initialization are all done here so we
         * can recall function without having locking issues */
-       mutex_init(&rdev->cs_mutex);
+       radeon_mutex_init(&rdev->cs_mutex);
        mutex_init(&rdev->ib_pool.mutex);
        mutex_init(&rdev->cp.mutex);
        mutex_init(&rdev->dc_hw_i2c_mutex);
@@ -955,6 +955,9 @@ int radeon_gpu_reset(struct radeon_device *rdev)
        int r;
        int resched;
 
+       /* Prevent CS ioctl from interfering */
+       radeon_mutex_lock(&rdev->cs_mutex);
+
        radeon_save_bios_scratch_regs(rdev);
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
@@ -967,10 +970,15 @@ int radeon_gpu_reset(struct radeon_device *rdev)
                radeon_restore_bios_scratch_regs(rdev);
                drm_helper_resume_force_mode(rdev->ddev);
                ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-               return 0;
        }
-       /* bad news, how to tell it to userspace ? */
-       dev_info(rdev->dev, "GPU reset failed\n");
+
+       radeon_mutex_unlock(&rdev->cs_mutex);
+
+       if (r) {
+               /* bad news, how to tell it to userspace ? */
+               dev_info(rdev->dev, "GPU reset failed\n");
+       }
+
        return r;
 }
 
index 6adb3e58affdc3fccbce06e254cf648c6f4de5cb..a22d6e6a49a2649796a119c2b642a83659f8edd3 100644 (file)
@@ -33,8 +33,6 @@
 #include "drm_crtc_helper.h"
 #include "drm_edid.h"
 
-static int radeon_ddc_dump(struct drm_connector *connector);
-
 static void avivo_crtc_load_lut(struct drm_crtc *crtc)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -669,7 +667,6 @@ static void radeon_print_display_setup(struct drm_device *dev)
 static bool radeon_setup_enc_conn(struct drm_device *dev)
 {
        struct radeon_device *rdev = dev->dev_private;
-       struct drm_connector *drm_connector;
        bool ret = false;
 
        if (rdev->bios) {
@@ -689,8 +686,6 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
        if (ret) {
                radeon_setup_encoder_clones(dev);
                radeon_print_display_setup(dev);
-               list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
-                       radeon_ddc_dump(drm_connector);
        }
 
        return ret;
@@ -708,7 +703,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
 
        if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
            (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) ||
-           radeon_connector_encoder_is_dp_bridge(&radeon_connector->base)) {
+           (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
+            ENCODER_OBJECT_ID_NONE)) {
                struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
 
                if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
@@ -743,34 +739,6 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
        return 0;
 }
 
-static int radeon_ddc_dump(struct drm_connector *connector)
-{
-       struct edid *edid;
-       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-       int ret = 0;
-
-       /* on hw with routers, select right port */
-       if (radeon_connector->router.ddc_valid)
-               radeon_router_select_ddc_port(radeon_connector);
-
-       if (!radeon_connector->ddc_bus)
-               return -1;
-       edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
-       /* Log EDID retrieval status here. In particular with regard to
-        * connectors with requires_extended_probe flag set, that will prevent
-        * function radeon_dvi_detect() to fetch EDID on this connector,
-        * as long as there is no valid EDID header found */
-       if (edid) {
-               DRM_INFO("Radeon display connector %s: Found valid EDID",
-                               drm_get_connector_name(connector));
-               kfree(edid);
-       } else {
-               DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
-                               drm_get_connector_name(connector));
-       }
-       return ret;
-}
-
 /* avivo */
 static void avivo_get_fb_div(struct radeon_pll *pll,
                             u32 target_clock,
index 969933833ccb820f41f40a722733ae31f42250d4..71499fc3daf524f8b719692e9ff7aacb6219b2e9 100644 (file)
  *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
  *   2.10.0 - fusion 2D tiling
  *   2.11.0 - backend map, initial compute support for the CS checker
+ *   2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       11
+#define KMS_DRIVER_MINOR       12
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -119,6 +120,7 @@ int radeon_audio = 0;
 int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = 0;
+int radeon_msi = -1;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -165,6 +167,9 @@ module_param_named(hw_i2c, radeon_hw_i2c, int, 0444);
 MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)");
 module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
 
+MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
+module_param_named(msi, radeon_msi, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
index eb3f6dc6df835050dfacaae3a663f4a79f7f254c..06e413e6a920207850734185f1c459989616f625 100644 (file)
 #include "radeon.h"
 #include "atom.h"
 
-extern int atom_debug;
-
-/* evil but including atombios.h is much worse */
-bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
-                               struct drm_display_mode *mode);
-
 static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
@@ -156,27 +150,6 @@ radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8
        return ret;
 }
 
-static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
-{
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-       case ENCODER_OBJECT_ID_INTERNAL_DDI:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-               return true;
-       default:
-               return false;
-       }
-}
-
 void
 radeon_link_encoder_connector(struct drm_device *dev)
 {
@@ -229,23 +202,7 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
        return NULL;
 }
 
-static struct drm_connector *
-radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_connector *connector;
-       struct radeon_connector *radeon_connector;
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               radeon_connector = to_radeon_connector(connector);
-               if (radeon_encoder->devices & radeon_connector->devices)
-                       return connector;
-       }
-       return NULL;
-}
-
-struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder)
+struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -266,9 +223,9 @@ struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder
        return NULL;
 }
 
-bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder)
+u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder)
 {
-       struct drm_encoder *other_encoder = radeon_atom_get_external_encoder(encoder);
+       struct drm_encoder *other_encoder = radeon_get_external_encoder(encoder);
 
        if (other_encoder) {
                struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder);
@@ -332,2105 +289,3 @@ void radeon_panel_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);
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-
-       /* set the active encoder to connector routing */
-       radeon_encoder_set_active_device(encoder);
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-       /* hw bug */
-       if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
-           && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
-               adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
-
-       /* get the native mode for LVDS */
-       if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
-               radeon_panel_mode_fixup(encoder, adjusted_mode);
-
-       /* get the native mode for TV */
-       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
-               struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
-               if (tv_dac) {
-                       if (tv_dac->tv_std == TV_STD_NTSC ||
-                           tv_dac->tv_std == TV_STD_NTSC_J ||
-                           tv_dac->tv_std == TV_STD_PAL_M)
-                               radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
-                       else
-                               radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
-               }
-       }
-
-       if (ASIC_IS_DCE3(rdev) &&
-           ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
-            radeon_encoder_is_dp_bridge(encoder))) {
-               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-               radeon_dp_set_link_config(connector, mode);
-       }
-
-       return true;
-}
-
-static void
-atombios_dac_setup(struct drm_encoder *encoder, int action)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       DAC_ENCODER_CONTROL_PS_ALLOCATION args;
-       int index = 0;
-       struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
-
-       memset(&args, 0, sizeof(args));
-
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-               index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-               index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
-               break;
-       }
-
-       args.ucAction = action;
-
-       if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
-               args.ucDacStandard = ATOM_DAC1_PS2;
-       else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-               args.ucDacStandard = ATOM_DAC1_CV;
-       else {
-               switch (dac_info->tv_std) {
-               case TV_STD_PAL:
-               case TV_STD_PAL_M:
-               case TV_STD_SCART_PAL:
-               case TV_STD_SECAM:
-               case TV_STD_PAL_CN:
-                       args.ucDacStandard = ATOM_DAC1_PAL;
-                       break;
-               case TV_STD_NTSC:
-               case TV_STD_NTSC_J:
-               case TV_STD_PAL_60:
-               default:
-                       args.ucDacStandard = ATOM_DAC1_NTSC;
-                       break;
-               }
-       }
-       args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-static void
-atombios_tv_setup(struct drm_encoder *encoder, int action)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       TV_ENCODER_CONTROL_PS_ALLOCATION args;
-       int index = 0;
-       struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
-
-       memset(&args, 0, sizeof(args));
-
-       index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
-
-       args.sTVEncoder.ucAction = action;
-
-       if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-               args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
-       else {
-               switch (dac_info->tv_std) {
-               case TV_STD_NTSC:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
-                       break;
-               case TV_STD_PAL:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
-                       break;
-               case TV_STD_PAL_M:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
-                       break;
-               case TV_STD_PAL_60:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
-                       break;
-               case TV_STD_NTSC_J:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
-                       break;
-               case TV_STD_SCART_PAL:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
-                       break;
-               case TV_STD_SECAM:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
-                       break;
-               case TV_STD_PAL_CN:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
-                       break;
-               default:
-                       args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
-                       break;
-               }
-       }
-
-       args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-union dvo_encoder_control {
-       ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
-       DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
-       DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
-};
-
-void
-atombios_dvo_setup(struct drm_encoder *encoder, int action)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       union dvo_encoder_control args;
-       int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
-
-       memset(&args, 0, sizeof(args));
-
-       if (ASIC_IS_DCE3(rdev)) {
-               /* DCE3+ */
-               args.dvo_v3.ucAction = action;
-               args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-               args.dvo_v3.ucDVOConfig = 0; /* XXX */
-       } else if (ASIC_IS_DCE2(rdev)) {
-               /* DCE2 (pre-DCE3 R6xx, RS600/690/740 */
-               args.dvo.sDVOEncoder.ucAction = action;
-               args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-               /* DFP1, CRT1, TV1 depending on the type of port */
-               args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
-
-               if (radeon_encoder->pixel_clock > 165000)
-                       args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
-       } else {
-               /* R4xx, R5xx */
-               args.ext_tmds.sXTmdsEncoder.ucEnable = action;
-
-               if (radeon_encoder->pixel_clock > 165000)
-                       args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-
-               /*if (pScrn->rgbBits == 8)*/
-               args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
-       }
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-union lvds_encoder_control {
-       LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
-       LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
-};
-
-void
-atombios_digital_setup(struct drm_encoder *encoder, int action)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       union lvds_encoder_control args;
-       int index = 0;
-       int hdmi_detected = 0;
-       uint8_t frev, crev;
-
-       if (!dig)
-               return;
-
-       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
-               hdmi_detected = 1;
-
-       memset(&args, 0, sizeof(args));
-
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-               index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-               index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
-               else
-                       index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
-               break;
-       }
-
-       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-               return;
-
-       switch (frev) {
-       case 1:
-       case 2:
-               switch (crev) {
-               case 1:
-                       args.v1.ucMisc = 0;
-                       args.v1.ucAction = action;
-                       if (hdmi_detected)
-                               args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
-                       args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                               if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
-                                       args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-                               if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-                                       args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
-                       } else {
-                               if (dig->linkb)
-                                       args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
-                               if (radeon_encoder->pixel_clock > 165000)
-                                       args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-                               /*if (pScrn->rgbBits == 8) */
-                               args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
-                       }
-                       break;
-               case 2:
-               case 3:
-                       args.v2.ucMisc = 0;
-                       args.v2.ucAction = action;
-                       if (crev == 3) {
-                               if (dig->coherent_mode)
-                                       args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
-                       }
-                       if (hdmi_detected)
-                               args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
-                       args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-                       args.v2.ucTruncate = 0;
-                       args.v2.ucSpatial = 0;
-                       args.v2.ucTemporal = 0;
-                       args.v2.ucFRC = 0;
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                               if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
-                                       args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-                               if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
-                                       args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
-                                       if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-                                               args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
-                               }
-                               if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
-                                       args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
-                                       if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-                                               args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
-                                       if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
-                                               args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
-                               }
-                       } else {
-                               if (dig->linkb)
-                                       args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
-                               if (radeon_encoder->pixel_clock > 165000)
-                                       args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-                       }
-                       break;
-               default:
-                       DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
-                       break;
-               }
-               break;
-       default:
-               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
-               break;
-       }
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-int
-atombios_get_encoder_mode(struct drm_encoder *encoder)
-{
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct drm_connector *connector;
-       struct radeon_connector *radeon_connector;
-       struct radeon_connector_atom_dig *dig_connector;
-
-       /* dp bridges are always DP */
-       if (radeon_encoder_is_dp_bridge(encoder))
-               return ATOM_ENCODER_MODE_DP;
-
-       /* DVO is always DVO */
-       if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
-               return ATOM_ENCODER_MODE_DVO;
-
-       connector = radeon_get_connector_for_encoder(encoder);
-       /* if we don't have an active device yet, just use one of
-        * the connectors tied to the encoder.
-        */
-       if (!connector)
-               connector = radeon_get_connector_for_encoder_init(encoder);
-       radeon_connector = to_radeon_connector(connector);
-
-       switch (connector->connector_type) {
-       case DRM_MODE_CONNECTOR_DVII:
-       case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
-               if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-                       /* fix me */
-                       if (ASIC_IS_DCE4(rdev))
-                               return ATOM_ENCODER_MODE_DVI;
-                       else
-                               return ATOM_ENCODER_MODE_HDMI;
-               } else if (radeon_connector->use_digital)
-                       return ATOM_ENCODER_MODE_DVI;
-               else
-                       return ATOM_ENCODER_MODE_CRT;
-               break;
-       case DRM_MODE_CONNECTOR_DVID:
-       case DRM_MODE_CONNECTOR_HDMIA:
-       default:
-               if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-                       /* fix me */
-                       if (ASIC_IS_DCE4(rdev))
-                               return ATOM_ENCODER_MODE_DVI;
-                       else
-                               return ATOM_ENCODER_MODE_HDMI;
-               } else
-                       return ATOM_ENCODER_MODE_DVI;
-               break;
-       case DRM_MODE_CONNECTOR_LVDS:
-               return ATOM_ENCODER_MODE_LVDS;
-               break;
-       case DRM_MODE_CONNECTOR_DisplayPort:
-               dig_connector = radeon_connector->con_priv;
-               if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
-                   (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
-                       return ATOM_ENCODER_MODE_DP;
-               else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-                       /* fix me */
-                       if (ASIC_IS_DCE4(rdev))
-                               return ATOM_ENCODER_MODE_DVI;
-                       else
-                               return ATOM_ENCODER_MODE_HDMI;
-               } else
-                       return ATOM_ENCODER_MODE_DVI;
-               break;
-       case DRM_MODE_CONNECTOR_eDP:
-               return ATOM_ENCODER_MODE_DP;
-       case DRM_MODE_CONNECTOR_DVIA:
-       case DRM_MODE_CONNECTOR_VGA:
-               return ATOM_ENCODER_MODE_CRT;
-               break;
-       case DRM_MODE_CONNECTOR_Composite:
-       case DRM_MODE_CONNECTOR_SVIDEO:
-       case DRM_MODE_CONNECTOR_9PinDIN:
-               /* fix me */
-               return ATOM_ENCODER_MODE_TV;
-               /*return ATOM_ENCODER_MODE_CV;*/
-               break;
-       }
-}
-
-/*
- * DIG Encoder/Transmitter Setup
- *
- * DCE 3.0/3.1
- * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
- * Supports up to 3 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1 can drive UNIPHY link A or link B
- * DIG2 can drive UNIPHY link B or LVTMA
- *
- * DCE 3.2
- * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
- * Supports up to 5 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1/2 can drive UNIPHY0/1/2 link A or link B
- *
- * DCE 4.0/5.0
- * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
- * Supports up to 6 digital outputs
- * - 6 DIG encoder blocks.
- * - DIG to PHY mapping is hardcoded
- * DIG1 drives UNIPHY0 link A, A+B
- * DIG2 drives UNIPHY0 link B
- * DIG3 drives UNIPHY1 link A, A+B
- * DIG4 drives UNIPHY1 link B
- * DIG5 drives UNIPHY2 link A, A+B
- * DIG6 drives UNIPHY2 link B
- *
- * DCE 4.1
- * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
- * Supports up to 6 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1/2 can drive UNIPHY0/1/2 link A or link B
- *
- * Routing
- * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
- * Examples:
- * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
- * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
- * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
- * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
- */
-
-union dig_encoder_control {
-       DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
-       DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
-       DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
-       DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
-};
-
-void
-atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_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_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-       union dig_encoder_control args;
-       int index = 0;
-       uint8_t frev, crev;
-       int dp_clock = 0;
-       int dp_lane_count = 0;
-       int hpd_id = RADEON_HPD_NONE;
-       int bpc = 8;
-
-       if (connector) {
-               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-               struct radeon_connector_atom_dig *dig_connector =
-                       radeon_connector->con_priv;
-
-               dp_clock = dig_connector->dp_clock;
-               dp_lane_count = dig_connector->dp_lane_count;
-               hpd_id = radeon_connector->hpd.hpd;
-               bpc = connector->display_info.bpc;
-       }
-
-       /* no dig encoder assigned */
-       if (dig->dig_encoder == -1)
-               return;
-
-       memset(&args, 0, sizeof(args));
-
-       if (ASIC_IS_DCE4(rdev))
-               index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
-       else {
-               if (dig->dig_encoder)
-                       index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
-               else
-                       index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
-       }
-
-       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-               return;
-
-       args.v1.ucAction = action;
-       args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-       if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
-               args.v3.ucPanelMode = panel_mode;
-       else
-               args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-       if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
-           (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST))
-               args.v1.ucLaneNum = dp_lane_count;
-       else if (radeon_encoder->pixel_clock > 165000)
-               args.v1.ucLaneNum = 8;
-       else
-               args.v1.ucLaneNum = 4;
-
-       if (ASIC_IS_DCE5(rdev)) {
-               if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
-                   (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)) {
-                       if (dp_clock == 270000)
-                               args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
-                       else if (dp_clock == 540000)
-                               args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
-               }
-               args.v4.acConfig.ucDigSel = dig->dig_encoder;
-               switch (bpc) {
-               case 0:
-                       args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
-                       break;
-               case 6:
-                       args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-                       break;
-               case 8:
-               default:
-                       args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-                       break;
-               case 10:
-                       args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-                       break;
-               case 12:
-                       args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-                       break;
-               case 16:
-                       args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-                       break;
-               }
-               if (hpd_id == RADEON_HPD_NONE)
-                       args.v4.ucHPD_ID = 0;
-               else
-                       args.v4.ucHPD_ID = hpd_id + 1;
-       } else if (ASIC_IS_DCE4(rdev)) {
-               if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
-                       args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
-               args.v3.acConfig.ucDigSel = dig->dig_encoder;
-               switch (bpc) {
-               case 0:
-                       args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
-                       break;
-               case 6:
-                       args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-                       break;
-               case 8:
-               default:
-                       args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-                       break;
-               case 10:
-                       args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-                       break;
-               case 12:
-                       args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-                       break;
-               case 16:
-                       args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-                       break;
-               }
-       } else {
-               if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
-                       args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-               switch (radeon_encoder->encoder_id) {
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-                       args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
-                       break;
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-                       args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
-                       break;
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-                       args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
-                       break;
-               }
-               if (dig->linkb)
-                       args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
-               else
-                       args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
-       }
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-union dig_transmitter_control {
-       DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
-       DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
-       DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
-       DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
-};
-
-void
-atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       struct drm_connector *connector;
-       union dig_transmitter_control args;
-       int index = 0;
-       uint8_t frev, crev;
-       bool is_dp = false;
-       int pll_id = 0;
-       int dp_clock = 0;
-       int dp_lane_count = 0;
-       int connector_object_id = 0;
-       int igp_lane_info = 0;
-       int dig_encoder = dig->dig_encoder;
-
-       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-               connector = radeon_get_connector_for_encoder_init(encoder);
-               /* just needed to avoid bailing in the encoder check.  the encoder
-                * isn't used for init
-                */
-               dig_encoder = 0;
-       } else
-               connector = radeon_get_connector_for_encoder(encoder);
-
-       if (connector) {
-               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-               struct radeon_connector_atom_dig *dig_connector =
-                       radeon_connector->con_priv;
-
-               dp_clock = dig_connector->dp_clock;
-               dp_lane_count = dig_connector->dp_lane_count;
-               connector_object_id =
-                       (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-               igp_lane_info = dig_connector->igp_lane_info;
-       }
-
-       /* no dig encoder assigned */
-       if (dig_encoder == -1)
-               return;
-
-       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
-               is_dp = true;
-
-       memset(&args, 0, sizeof(args));
-
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-               index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-               index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
-               break;
-       }
-
-       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-               return;
-
-       args.v1.ucAction = action;
-       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-               args.v1.usInitInfo = cpu_to_le16(connector_object_id);
-       } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
-               args.v1.asMode.ucLaneSel = lane_num;
-               args.v1.asMode.ucLaneSet = lane_set;
-       } else {
-               if (is_dp)
-                       args.v1.usPixelClock =
-                               cpu_to_le16(dp_clock / 10);
-               else if (radeon_encoder->pixel_clock > 165000)
-                       args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
-               else
-                       args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-       }
-       if (ASIC_IS_DCE4(rdev)) {
-               if (is_dp)
-                       args.v3.ucLaneNum = dp_lane_count;
-               else if (radeon_encoder->pixel_clock > 165000)
-                       args.v3.ucLaneNum = 8;
-               else
-                       args.v3.ucLaneNum = 4;
-
-               if (dig->linkb)
-                       args.v3.acConfig.ucLinkSel = 1;
-               if (dig_encoder & 1)
-                       args.v3.acConfig.ucEncoderSel = 1;
-
-               /* Select the PLL for the PHY
-                * DP PHY should be clocked from external src if there is
-                * one.
-                */
-               if (encoder->crtc) {
-                       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-                       pll_id = radeon_crtc->pll_id;
-               }
-
-               if (ASIC_IS_DCE5(rdev)) {
-                       /* On DCE5 DCPLL usually generates the DP ref clock */
-                       if (is_dp) {
-                               if (rdev->clock.dp_extclk)
-                                       args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
-                               else
-                                       args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
-                       } else
-                               args.v4.acConfig.ucRefClkSource = pll_id;
-               } else {
-                       /* On DCE4, if there is an external clock, it generates the DP ref clock */
-                       if (is_dp && rdev->clock.dp_extclk)
-                               args.v3.acConfig.ucRefClkSource = 2; /* external src */
-                       else
-                               args.v3.acConfig.ucRefClkSource = pll_id;
-               }
-
-               switch (radeon_encoder->encoder_id) {
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-                       args.v3.acConfig.ucTransmitterSel = 0;
-                       break;
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-                       args.v3.acConfig.ucTransmitterSel = 1;
-                       break;
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-                       args.v3.acConfig.ucTransmitterSel = 2;
-                       break;
-               }
-
-               if (is_dp)
-                       args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
-               else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-                       if (dig->coherent_mode)
-                               args.v3.acConfig.fCoherentMode = 1;
-                       if (radeon_encoder->pixel_clock > 165000)
-                               args.v3.acConfig.fDualLinkConnector = 1;
-               }
-       } else if (ASIC_IS_DCE32(rdev)) {
-               args.v2.acConfig.ucEncoderSel = dig_encoder;
-               if (dig->linkb)
-                       args.v2.acConfig.ucLinkSel = 1;
-
-               switch (radeon_encoder->encoder_id) {
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-                       args.v2.acConfig.ucTransmitterSel = 0;
-                       break;
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-                       args.v2.acConfig.ucTransmitterSel = 1;
-                       break;
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-                       args.v2.acConfig.ucTransmitterSel = 2;
-                       break;
-               }
-
-               if (is_dp) {
-                       args.v2.acConfig.fCoherentMode = 1;
-                       args.v2.acConfig.fDPConnector = 1;
-               } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-                       if (dig->coherent_mode)
-                               args.v2.acConfig.fCoherentMode = 1;
-                       if (radeon_encoder->pixel_clock > 165000)
-                               args.v2.acConfig.fDualLinkConnector = 1;
-               }
-       } else {
-               args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
-
-               if (dig_encoder)
-                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
-               else
-                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
-
-               if ((rdev->flags & RADEON_IS_IGP) &&
-                   (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
-                       if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
-                               if (igp_lane_info & 0x1)
-                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-                               else if (igp_lane_info & 0x2)
-                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
-                               else if (igp_lane_info & 0x4)
-                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
-                               else if (igp_lane_info & 0x8)
-                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
-                       } else {
-                               if (igp_lane_info & 0x3)
-                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
-                               else if (igp_lane_info & 0xc)
-                                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
-                       }
-               }
-
-               if (dig->linkb)
-                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
-               else
-                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
-
-               if (is_dp)
-                       args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
-               else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-                       if (dig->coherent_mode)
-                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
-                       if (radeon_encoder->pixel_clock > 165000)
-                               args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
-               }
-       }
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-bool
-atombios_set_edp_panel_power(struct drm_connector *connector, int action)
-{
-       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-       struct drm_device *dev = radeon_connector->base.dev;
-       struct radeon_device *rdev = dev->dev_private;
-       union dig_transmitter_control args;
-       int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
-       uint8_t frev, crev;
-
-       if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
-               goto done;
-
-       if (!ASIC_IS_DCE4(rdev))
-               goto done;
-
-       if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
-           (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
-               goto done;
-
-       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-               goto done;
-
-       memset(&args, 0, sizeof(args));
-
-       args.v1.ucAction = action;
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-       /* wait for the panel to power up */
-       if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
-               int i;
-
-               for (i = 0; i < 300; i++) {
-                       if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
-                               return true;
-                       mdelay(1);
-               }
-               return false;
-       }
-done:
-       return true;
-}
-
-union external_encoder_control {
-       EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
-       EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
-};
-
-static void
-atombios_external_encoder_setup(struct drm_encoder *encoder,
-                               struct drm_encoder *ext_encoder,
-                               int action)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
-       union external_encoder_control args;
-       struct drm_connector *connector;
-       int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
-       u8 frev, crev;
-       int dp_clock = 0;
-       int dp_lane_count = 0;
-       int connector_object_id = 0;
-       u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
-       int bpc = 8;
-
-       if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
-               connector = radeon_get_connector_for_encoder_init(encoder);
-       else
-               connector = radeon_get_connector_for_encoder(encoder);
-
-       if (connector) {
-               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-               struct radeon_connector_atom_dig *dig_connector =
-                       radeon_connector->con_priv;
-
-               dp_clock = dig_connector->dp_clock;
-               dp_lane_count = dig_connector->dp_lane_count;
-               connector_object_id =
-                       (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-               bpc = connector->display_info.bpc;
-       }
-
-       memset(&args, 0, sizeof(args));
-
-       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-               return;
-
-       switch (frev) {
-       case 1:
-               /* no params on frev 1 */
-               break;
-       case 2:
-               switch (crev) {
-               case 1:
-               case 2:
-                       args.v1.sDigEncoder.ucAction = action;
-                       args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-                       args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-                       if (args.v1.sDigEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-                               if (dp_clock == 270000)
-                                       args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-                               args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
-                       } else if (radeon_encoder->pixel_clock > 165000)
-                               args.v1.sDigEncoder.ucLaneNum = 8;
-                       else
-                               args.v1.sDigEncoder.ucLaneNum = 4;
-                       break;
-               case 3:
-                       args.v3.sExtEncoder.ucAction = action;
-                       if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
-                               args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
-                       else
-                               args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-                       args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-                       if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-                               if (dp_clock == 270000)
-                                       args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
-                               else if (dp_clock == 540000)
-                                       args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
-                               args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
-                       } else if (radeon_encoder->pixel_clock > 165000)
-                               args.v3.sExtEncoder.ucLaneNum = 8;
-                       else
-                               args.v3.sExtEncoder.ucLaneNum = 4;
-                       switch (ext_enum) {
-                       case GRAPH_OBJECT_ENUM_ID1:
-                               args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
-                               break;
-                       case GRAPH_OBJECT_ENUM_ID2:
-                               args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
-                               break;
-                       case GRAPH_OBJECT_ENUM_ID3:
-                               args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
-                               break;
-                       }
-                       switch (bpc) {
-                       case 0:
-                               args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE;
-                               break;
-                       case 6:
-                               args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-                               break;
-                       case 8:
-                       default:
-                               args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-                               break;
-                       case 10:
-                               args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-                               break;
-                       case 12:
-                               args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-                               break;
-                       case 16:
-                               args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-                               break;
-                       }
-                       break;
-               default:
-                       DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-                       return;
-               }
-               break;
-       default:
-               DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-               return;
-       }
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-static void
-atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
-{
-       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_YUV_PS_ALLOCATION args;
-       int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
-       uint32_t temp, reg;
-
-       memset(&args, 0, sizeof(args));
-
-       if (rdev->family >= CHIP_R600)
-               reg = R600_BIOS_3_SCRATCH;
-       else
-               reg = RADEON_BIOS_3_SCRATCH;
-
-       /* XXX: fix up scratch reg handling */
-       temp = RREG32(reg);
-       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-               WREG32(reg, (ATOM_S3_TV1_ACTIVE |
-                            (radeon_crtc->crtc_id << 18)));
-       else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-               WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
-       else
-               WREG32(reg, 0);
-
-       if (enable)
-               args.ucEnable = ATOM_ENABLE;
-       args.ucCRTC = radeon_crtc->crtc_id;
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-       WREG32(reg, temp);
-}
-
-static void
-radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-       DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
-       int index = 0;
-       bool is_dig = false;
-       bool is_dce5_dac = false;
-       bool is_dce5_dvo = false;
-
-       memset(&args, 0, sizeof(args));
-
-       DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
-                 radeon_encoder->encoder_id, mode, radeon_encoder->devices,
-                 radeon_encoder->active_device);
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-               index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               is_dig = true;
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-       case ENCODER_OBJECT_ID_INTERNAL_DDI:
-               index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-               if (ASIC_IS_DCE5(rdev))
-                       is_dce5_dvo = true;
-               else if (ASIC_IS_DCE3(rdev))
-                       is_dig = true;
-               else
-                       index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-               index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
-               else
-                       index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-               if (ASIC_IS_DCE5(rdev))
-                       is_dce5_dac = true;
-               else {
-                       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-                               index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-                       else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-                               index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
-                       else
-                               index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
-               }
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-                       index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-                       index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
-               else
-                       index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
-               break;
-       }
-
-       if (is_dig) {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-                       /* some early dce3.2 boards have a bug in their transmitter control table */
-                       if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-                       else
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
-                       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
-                               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-                               if (connector &&
-                                   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
-                                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-                                       struct radeon_connector_atom_dig *radeon_dig_connector =
-                                               radeon_connector->con_priv;
-                                       atombios_set_edp_panel_power(connector,
-                                                                    ATOM_TRANSMITTER_ACTION_POWER_ON);
-                                       radeon_dig_connector->edp_on = true;
-                               }
-                               if (ASIC_IS_DCE4(rdev))
-                                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-                               radeon_dp_link_train(encoder, connector);
-                               if (ASIC_IS_DCE4(rdev))
-                                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
-                       }
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
-                       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
-                               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-                               if (ASIC_IS_DCE4(rdev))
-                                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-                               if (connector &&
-                                   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
-                                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-                                       struct radeon_connector_atom_dig *radeon_dig_connector =
-                                               radeon_connector->con_priv;
-                                       atombios_set_edp_panel_power(connector,
-                                                                    ATOM_TRANSMITTER_ACTION_POWER_OFF);
-                                       radeon_dig_connector->edp_on = false;
-                               }
-                       }
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
-                       break;
-               }
-       } else if (is_dce5_dac) {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-                       atombios_dac_setup(encoder, ATOM_ENABLE);
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       atombios_dac_setup(encoder, ATOM_DISABLE);
-                       break;
-               }
-       } else if (is_dce5_dvo) {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-                       atombios_dvo_setup(encoder, ATOM_ENABLE);
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       atombios_dvo_setup(encoder, ATOM_DISABLE);
-                       break;
-               }
-       } else {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-                       args.ucAction = ATOM_ENABLE;
-                       /* workaround for DVOOutputControl on some RS690 systems */
-                       if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
-                               u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
-                               WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
-                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                               WREG32(RADEON_BIOS_3_SCRATCH, reg);
-                       } else
-                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                               args.ucAction = ATOM_LCD_BLON;
-                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                       }
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       args.ucAction = ATOM_DISABLE;
-                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                               args.ucAction = ATOM_LCD_BLOFF;
-                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                       }
-                       break;
-               }
-       }
-
-       if (ext_encoder) {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-               default:
-                       if (ASIC_IS_DCE41(rdev)) {
-                               atombios_external_encoder_setup(encoder, ext_encoder,
-                                                               EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
-                               atombios_external_encoder_setup(encoder, ext_encoder,
-                                                               EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
-                       } else
-                               atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       if (ASIC_IS_DCE41(rdev)) {
-                               atombios_external_encoder_setup(encoder, ext_encoder,
-                                                               EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
-                               atombios_external_encoder_setup(encoder, ext_encoder,
-                                                               EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
-                       } else
-                               atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
-                       break;
-               }
-       }
-
-       radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
-
-}
-
-union crtc_source_param {
-       SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
-       SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
-};
-
-static void
-atombios_set_encoder_crtc_source(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);
-       union crtc_source_param args;
-       int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
-       uint8_t frev, crev;
-       struct radeon_encoder_atom_dig *dig;
-
-       memset(&args, 0, sizeof(args));
-
-       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-               return;
-
-       switch (frev) {
-       case 1:
-               switch (crev) {
-               case 1:
-               default:
-                       if (ASIC_IS_AVIVO(rdev))
-                               args.v1.ucCRTC = radeon_crtc->crtc_id;
-                       else {
-                               if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
-                                       args.v1.ucCRTC = radeon_crtc->crtc_id;
-                               } else {
-                                       args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
-                               }
-                       }
-                       switch (radeon_encoder->encoder_id) {
-                       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-                               args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-                       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-                               if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
-                                       args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
-                               else
-                                       args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-                       case ENCODER_OBJECT_ID_INTERNAL_DDI:
-                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-                               args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-                               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-                                       args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
-                               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-                                       args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
-                               else
-                                       args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-                               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-                                       args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
-                               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-                                       args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
-                               else
-                                       args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
-                               break;
-                       }
-                       break;
-               case 2:
-                       args.v2.ucCRTC = radeon_crtc->crtc_id;
-                       if (radeon_encoder_is_dp_bridge(encoder)) {
-                               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-                               if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
-                                       args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
-                               else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
-                                       args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
-                               else
-                                       args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
-                       } else
-                               args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
-                       switch (radeon_encoder->encoder_id) {
-                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-                               dig = radeon_encoder->enc_priv;
-                               switch (dig->dig_encoder) {
-                               case 0:
-                                       args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
-                                       break;
-                               case 1:
-                                       args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
-                                       break;
-                               case 2:
-                                       args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
-                                       break;
-                               case 3:
-                                       args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
-                                       break;
-                               case 4:
-                                       args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
-                                       break;
-                               case 5:
-                                       args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
-                                       break;
-                               }
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-                               args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-                               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-                                       args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-                               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-                                       args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-                               else
-                                       args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-                               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-                                       args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-                               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-                                       args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-                               else
-                                       args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
-                               break;
-                       }
-                       break;
-               }
-               break;
-       default:
-               DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-               return;
-       }
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-       /* update scratch regs with new routing */
-       radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
-}
-
-static void
-atombios_apply_encoder_quirks(struct drm_encoder *encoder,
-                             struct drm_display_mode *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);
-
-       /* Funky macbooks */
-       if ((dev->pdev->device == 0x71C5) &&
-           (dev->pdev->subsystem_vendor == 0x106b) &&
-           (dev->pdev->subsystem_device == 0x0080)) {
-               if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
-                       uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
-
-                       lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
-                       lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
-
-                       WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
-               }
-       }
-
-       /* set scaler clears this on some chips */
-       if (ASIC_IS_AVIVO(rdev) &&
-           (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
-               if (ASIC_IS_DCE4(rdev)) {
-                       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-                               WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
-                                      EVERGREEN_INTERLEAVE_EN);
-                       else
-                               WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
-               } else {
-                       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-                               WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
-                                      AVIVO_D1MODE_INTERLEAVE_EN);
-                       else
-                               WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
-               }
-       }
-}
-
-static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_encoder *test_encoder;
-       struct radeon_encoder_atom_dig *dig;
-       uint32_t dig_enc_in_use = 0;
-
-       /* DCE4/5 */
-       if (ASIC_IS_DCE4(rdev)) {
-               dig = radeon_encoder->enc_priv;
-               if (ASIC_IS_DCE41(rdev)) {
-                       /* ontario follows DCE4 */
-                       if (rdev->family == CHIP_PALM) {
-                               if (dig->linkb)
-                                       return 1;
-                               else
-                                       return 0;
-                       } else
-                               /* llano follows DCE3.2 */
-                               return radeon_crtc->crtc_id;
-               } else {
-                       switch (radeon_encoder->encoder_id) {
-                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-                               if (dig->linkb)
-                                       return 1;
-                               else
-                                       return 0;
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-                               if (dig->linkb)
-                                       return 3;
-                               else
-                                       return 2;
-                               break;
-                       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-                               if (dig->linkb)
-                                       return 5;
-                               else
-                                       return 4;
-                               break;
-                       }
-               }
-       }
-
-       /* on DCE32 and encoder can driver any block so just crtc id */
-       if (ASIC_IS_DCE32(rdev)) {
-               return radeon_crtc->crtc_id;
-       }
-
-       /* on DCE3 - LVTMA can only be driven by DIGB */
-       list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
-               struct radeon_encoder *radeon_test_encoder;
-
-               if (encoder == test_encoder)
-                       continue;
-
-               if (!radeon_encoder_is_digital(test_encoder))
-                       continue;
-
-               radeon_test_encoder = to_radeon_encoder(test_encoder);
-               dig = radeon_test_encoder->enc_priv;
-
-               if (dig->dig_encoder >= 0)
-                       dig_enc_in_use |= (1 << dig->dig_encoder);
-       }
-
-       if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
-               if (dig_enc_in_use & 0x2)
-                       DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
-               return 1;
-       }
-       if (!(dig_enc_in_use & 1))
-               return 0;
-       return 1;
-}
-
-/* This only needs to be called once at startup */
-void
-radeon_atom_encoder_init(struct radeon_device *rdev)
-{
-       struct drm_device *dev = rdev->ddev;
-       struct drm_encoder *encoder;
-
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-               struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-               switch (radeon_encoder->encoder_id) {
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
-                       break;
-               default:
-                       break;
-               }
-
-               if (ext_encoder && ASIC_IS_DCE41(rdev))
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
-       }
-}
-
-static void
-radeon_atom_encoder_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);
-       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-       radeon_encoder->pixel_clock = adjusted_mode->clock;
-
-       if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
-               if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
-                       atombios_yuv_setup(encoder, true);
-               else
-                       atombios_yuv_setup(encoder, false);
-       }
-
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-               atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               if (ASIC_IS_DCE4(rdev)) {
-                       /* disable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-                       /* setup and enable the encoder */
-                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
-
-                       /* enable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-               } else {
-                       /* disable the encoder and transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-                       atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-
-                       /* setup and enable the encoder and transmitter */
-                       atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-               }
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DDI:
-       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-               atombios_dvo_setup(encoder, ATOM_ENABLE);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-               atombios_dac_setup(encoder, ATOM_ENABLE);
-               if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
-                       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-                               atombios_tv_setup(encoder, ATOM_ENABLE);
-                       else
-                               atombios_tv_setup(encoder, ATOM_DISABLE);
-               }
-               break;
-       }
-
-       if (ext_encoder) {
-               if (ASIC_IS_DCE41(rdev))
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
-               else
-                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-       }
-
-       atombios_apply_encoder_quirks(encoder, adjusted_mode);
-
-       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
-               r600_hdmi_enable(encoder);
-               r600_hdmi_setmode(encoder, adjusted_mode);
-       }
-}
-
-static bool
-atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-
-       if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
-                                      ATOM_DEVICE_CV_SUPPORT |
-                                      ATOM_DEVICE_CRT_SUPPORT)) {
-               DAC_LOAD_DETECTION_PS_ALLOCATION args;
-               int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
-               uint8_t frev, crev;
-
-               memset(&args, 0, sizeof(args));
-
-               if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-                       return false;
-
-               args.sDacload.ucMisc = 0;
-
-               if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
-                   (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
-                       args.sDacload.ucDacType = ATOM_DAC_A;
-               else
-                       args.sDacload.ucDacType = ATOM_DAC_B;
-
-               if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
-                       args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
-               else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
-                       args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
-               else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-                       args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
-                       if (crev >= 3)
-                               args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
-               } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-                       args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
-                       if (crev >= 3)
-                               args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
-               }
-
-               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-               return true;
-       } else
-               return false;
-}
-
-static enum drm_connector_status
-radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-       uint32_t bios_0_scratch;
-
-       if (!atombios_dac_load_detect(encoder, connector)) {
-               DRM_DEBUG_KMS("detect returned false \n");
-               return connector_status_unknown;
-       }
-
-       if (rdev->family >= CHIP_R600)
-               bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
-       else
-               bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
-
-       DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
-       if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
-               if (bios_0_scratch & ATOM_S0_CRT1_MASK)
-                       return connector_status_connected;
-       }
-       if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
-               if (bios_0_scratch & ATOM_S0_CRT2_MASK)
-                       return connector_status_connected;
-       }
-       if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-               if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
-                       return connector_status_connected;
-       }
-       if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-               if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
-                       return connector_status_connected; /* CTV */
-               else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
-                       return connector_status_connected; /* STV */
-       }
-       return connector_status_disconnected;
-}
-
-static enum drm_connector_status
-radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-       u32 bios_0_scratch;
-
-       if (!ASIC_IS_DCE4(rdev))
-               return connector_status_unknown;
-
-       if (!ext_encoder)
-               return connector_status_unknown;
-
-       if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
-               return connector_status_unknown;
-
-       /* load detect on the dp bridge */
-       atombios_external_encoder_setup(encoder, ext_encoder,
-                                       EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
-
-       bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
-
-       DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
-       if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
-               if (bios_0_scratch & ATOM_S0_CRT1_MASK)
-                       return connector_status_connected;
-       }
-       if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
-               if (bios_0_scratch & ATOM_S0_CRT2_MASK)
-                       return connector_status_connected;
-       }
-       if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-               if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
-                       return connector_status_connected;
-       }
-       if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-               if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
-                       return connector_status_connected; /* CTV */
-               else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
-                       return connector_status_connected; /* STV */
-       }
-       return connector_status_disconnected;
-}
-
-void
-radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
-{
-       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-       if (ext_encoder)
-               /* ddc_setup on the dp bridge */
-               atombios_external_encoder_setup(encoder, ext_encoder,
-                                               EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
-
-}
-
-static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
-{
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-       if ((radeon_encoder->active_device &
-            (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
-           radeon_encoder_is_dp_bridge(encoder)) {
-               struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-               if (dig)
-                       dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
-       }
-
-       radeon_atom_output_lock(encoder, true);
-       radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-
-       if (connector) {
-               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-
-               /* select the clock/data port if it uses a router */
-               if (radeon_connector->router.cd_valid)
-                       radeon_router_select_cd_port(radeon_connector);
-
-               /* turn eDP panel on for mode set */
-               if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
-                       atombios_set_edp_panel_power(connector,
-                                                    ATOM_TRANSMITTER_ACTION_POWER_ON);
-       }
-
-       /* this is needed for the pll/ss setup to work correctly in some cases */
-       atombios_set_encoder_crtc_source(encoder);
-}
-
-static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
-{
-       radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
-       radeon_atom_output_lock(encoder, false);
-}
-
-static void radeon_atom_encoder_disable(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_encoder_atom_dig *dig;
-
-       /* check for pre-DCE3 cards with shared encoders;
-        * can't really use the links individually, so don't disable
-        * the encoder if it's in use by another connector
-        */
-       if (!ASIC_IS_DCE3(rdev)) {
-               struct drm_encoder *other_encoder;
-               struct radeon_encoder *other_radeon_encoder;
-
-               list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
-                       other_radeon_encoder = to_radeon_encoder(other_encoder);
-                       if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
-                           drm_helper_encoder_in_use(other_encoder))
-                               goto disable_done;
-               }
-       }
-
-       radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-               atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               if (ASIC_IS_DCE4(rdev))
-                       /* disable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-               else {
-                       /* disable the encoder and transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-                       atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-               }
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DDI:
-       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-               atombios_dvo_setup(encoder, ATOM_DISABLE);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-               atombios_dac_setup(encoder, ATOM_DISABLE);
-               if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-                       atombios_tv_setup(encoder, ATOM_DISABLE);
-               break;
-       }
-
-disable_done:
-       if (radeon_encoder_is_digital(encoder)) {
-               if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
-                       r600_hdmi_disable(encoder);
-               dig = radeon_encoder->enc_priv;
-               dig->dig_encoder = -1;
-       }
-       radeon_encoder->active_device = 0;
-}
-
-/* these are handled by the primary encoders */
-static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
-{
-
-}
-
-static void radeon_atom_ext_commit(struct drm_encoder *encoder)
-{
-
-}
-
-static void
-radeon_atom_ext_mode_set(struct drm_encoder *encoder,
-                        struct drm_display_mode *mode,
-                        struct drm_display_mode *adjusted_mode)
-{
-
-}
-
-static void radeon_atom_ext_disable(struct drm_encoder *encoder)
-{
-
-}
-
-static void
-radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
-{
-
-}
-
-static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
-                                      struct drm_display_mode *mode,
-                                      struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
-       .dpms = radeon_atom_ext_dpms,
-       .mode_fixup = radeon_atom_ext_mode_fixup,
-       .prepare = radeon_atom_ext_prepare,
-       .mode_set = radeon_atom_ext_mode_set,
-       .commit = radeon_atom_ext_commit,
-       .disable = radeon_atom_ext_disable,
-       /* no detect for TMDS/LVDS yet */
-};
-
-static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
-       .dpms = radeon_atom_encoder_dpms,
-       .mode_fixup = radeon_atom_mode_fixup,
-       .prepare = radeon_atom_encoder_prepare,
-       .mode_set = radeon_atom_encoder_mode_set,
-       .commit = radeon_atom_encoder_commit,
-       .disable = radeon_atom_encoder_disable,
-       .detect = radeon_atom_dig_detect,
-};
-
-static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
-       .dpms = radeon_atom_encoder_dpms,
-       .mode_fixup = radeon_atom_mode_fixup,
-       .prepare = radeon_atom_encoder_prepare,
-       .mode_set = radeon_atom_encoder_mode_set,
-       .commit = radeon_atom_encoder_commit,
-       .detect = radeon_atom_dac_detect,
-};
-
-void radeon_enc_destroy(struct drm_encoder *encoder)
-{
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       kfree(radeon_encoder->enc_priv);
-       drm_encoder_cleanup(encoder);
-       kfree(radeon_encoder);
-}
-
-static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
-       .destroy = radeon_enc_destroy,
-};
-
-struct radeon_encoder_atom_dac *
-radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
-{
-       struct drm_device *dev = radeon_encoder->base.dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
-
-       if (!dac)
-               return NULL;
-
-       dac->tv_std = radeon_atombios_get_tv_info(rdev);
-       return dac;
-}
-
-struct radeon_encoder_atom_dig *
-radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
-{
-       int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
-       struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
-
-       if (!dig)
-               return NULL;
-
-       /* coherent mode by default */
-       dig->coherent_mode = true;
-       dig->dig_encoder = -1;
-
-       if (encoder_enum == 2)
-               dig->linkb = true;
-       else
-               dig->linkb = false;
-
-       return dig;
-}
-
-void
-radeon_add_atom_encoder(struct drm_device *dev,
-                       uint32_t encoder_enum,
-                       uint32_t supported_device,
-                       u16 caps)
-{
-       struct radeon_device *rdev = dev->dev_private;
-       struct drm_encoder *encoder;
-       struct radeon_encoder *radeon_encoder;
-
-       /* see if we already added it */
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               radeon_encoder = to_radeon_encoder(encoder);
-               if (radeon_encoder->encoder_enum == encoder_enum) {
-                       radeon_encoder->devices |= supported_device;
-                       return;
-               }
-
-       }
-
-       /* add a new one */
-       radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
-       if (!radeon_encoder)
-               return;
-
-       encoder = &radeon_encoder->base;
-       switch (rdev->num_crtc) {
-       case 1:
-               encoder->possible_crtcs = 0x1;
-               break;
-       case 2:
-       default:
-               encoder->possible_crtcs = 0x3;
-               break;
-       case 4:
-               encoder->possible_crtcs = 0xf;
-               break;
-       case 6:
-               encoder->possible_crtcs = 0x3f;
-               break;
-       }
-
-       radeon_encoder->enc_priv = NULL;
-
-       radeon_encoder->encoder_enum = encoder_enum;
-       radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-       radeon_encoder->devices = supported_device;
-       radeon_encoder->rmx_type = RMX_OFF;
-       radeon_encoder->underscan_type = UNDERSCAN_OFF;
-       radeon_encoder->is_ext_encoder = false;
-       radeon_encoder->caps = caps;
-
-       switch (radeon_encoder->encoder_id) {
-       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                       radeon_encoder->rmx_type = RMX_FULL;
-                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-                       radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
-               } else {
-                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-                       radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-               }
-               drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-               drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-               radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
-               drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-               drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
-               radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
-               drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
-               break;
-       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-       case ENCODER_OBJECT_ID_INTERNAL_DDI:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                       radeon_encoder->rmx_type = RMX_FULL;
-                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-                       radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
-               } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
-                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-                       radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-               } else {
-                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-                       radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-               }
-               drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
-               break;
-       case ENCODER_OBJECT_ID_SI170B:
-       case ENCODER_OBJECT_ID_CH7303:
-       case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
-       case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
-       case ENCODER_OBJECT_ID_TITFP513:
-       case ENCODER_OBJECT_ID_VT1623:
-       case ENCODER_OBJECT_ID_HDMI_SI1930:
-       case ENCODER_OBJECT_ID_TRAVIS:
-       case ENCODER_OBJECT_ID_NUTMEG:
-               /* these are handled by the primary encoders */
-               radeon_encoder->is_ext_encoder = true;
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-               else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
-                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-               else
-                       drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-               drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
-               break;
-       }
-}
index fdc3a9a54bf8e13cd6e4d9d475630cbec546b3b3..ba7ab79e12c1969793520a0ede951c675a52b469 100644 (file)
@@ -49,27 +49,27 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev)
                              rdev->gart.table_size >> PAGE_SHIFT);
        }
 #endif
-       rdev->gart.table.ram.ptr = ptr;
-       memset((void *)rdev->gart.table.ram.ptr, 0, rdev->gart.table_size);
+       rdev->gart.ptr = ptr;
+       memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size);
        return 0;
 }
 
 void radeon_gart_table_ram_free(struct radeon_device *rdev)
 {
-       if (rdev->gart.table.ram.ptr == NULL) {
+       if (rdev->gart.ptr == NULL) {
                return;
        }
 #ifdef CONFIG_X86
        if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
            rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
-               set_memory_wb((unsigned long)rdev->gart.table.ram.ptr,
+               set_memory_wb((unsigned long)rdev->gart.ptr,
                              rdev->gart.table_size >> PAGE_SHIFT);
        }
 #endif
        pci_free_consistent(rdev->pdev, rdev->gart.table_size,
-                           (void *)rdev->gart.table.ram.ptr,
+                           (void *)rdev->gart.ptr,
                            rdev->gart.table_addr);
-       rdev->gart.table.ram.ptr = NULL;
+       rdev->gart.ptr = NULL;
        rdev->gart.table_addr = 0;
 }
 
@@ -77,10 +77,10 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                r = radeon_bo_create(rdev, rdev->gart.table_size,
                                     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-                                    &rdev->gart.table.vram.robj);
+                                    &rdev->gart.robj);
                if (r) {
                        return r;
                }
@@ -93,38 +93,46 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev)
        uint64_t gpu_addr;
        int r;
 
-       r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+       r = radeon_bo_reserve(rdev->gart.robj, false);
        if (unlikely(r != 0))
                return r;
-       r = radeon_bo_pin(rdev->gart.table.vram.robj,
+       r = radeon_bo_pin(rdev->gart.robj,
                                RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
        if (r) {
-               radeon_bo_unreserve(rdev->gart.table.vram.robj);
+               radeon_bo_unreserve(rdev->gart.robj);
                return r;
        }
-       r = radeon_bo_kmap(rdev->gart.table.vram.robj,
-                               (void **)&rdev->gart.table.vram.ptr);
+       r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr);
        if (r)
-               radeon_bo_unpin(rdev->gart.table.vram.robj);
-       radeon_bo_unreserve(rdev->gart.table.vram.robj);
+               radeon_bo_unpin(rdev->gart.robj);
+       radeon_bo_unreserve(rdev->gart.robj);
        rdev->gart.table_addr = gpu_addr;
        return r;
 }
 
-void radeon_gart_table_vram_free(struct radeon_device *rdev)
+void radeon_gart_table_vram_unpin(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                return;
        }
-       r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+       r = radeon_bo_reserve(rdev->gart.robj, false);
        if (likely(r == 0)) {
-               radeon_bo_kunmap(rdev->gart.table.vram.robj);
-               radeon_bo_unpin(rdev->gart.table.vram.robj);
-               radeon_bo_unreserve(rdev->gart.table.vram.robj);
+               radeon_bo_kunmap(rdev->gart.robj);
+               radeon_bo_unpin(rdev->gart.robj);
+               radeon_bo_unreserve(rdev->gart.robj);
+               rdev->gart.ptr = NULL;
        }
-       radeon_bo_unref(&rdev->gart.table.vram.robj);
+}
+
+void radeon_gart_table_vram_free(struct radeon_device *rdev)
+{
+       if (rdev->gart.robj == NULL) {
+               return;
+       }
+       radeon_gart_table_vram_unpin(rdev);
+       radeon_bo_unref(&rdev->gart.robj);
 }
 
 
@@ -151,12 +159,14 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
                if (rdev->gart.pages[p]) {
                        if (!rdev->gart.ttm_alloced[p])
                                pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
-                                               PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+                                               PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
                        rdev->gart.pages[p] = NULL;
                        rdev->gart.pages_addr[p] = rdev->dummy_page.addr;
                        page_base = rdev->gart.pages_addr[p];
                        for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-                               radeon_gart_set_page(rdev, t, page_base);
+                               if (rdev->gart.ptr) {
+                                       radeon_gart_set_page(rdev, t, page_base);
+                               }
                                page_base += RADEON_GPU_PAGE_SIZE;
                        }
                }
@@ -199,10 +209,12 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
                        }
                }
                rdev->gart.pages[p] = pagelist[i];
-               page_base = rdev->gart.pages_addr[p];
-               for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-                       radeon_gart_set_page(rdev, t, page_base);
-                       page_base += RADEON_GPU_PAGE_SIZE;
+               if (rdev->gart.ptr) {
+                       page_base = rdev->gart.pages_addr[p];
+                       for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
+                               radeon_gart_set_page(rdev, t, page_base);
+                               page_base += RADEON_GPU_PAGE_SIZE;
+                       }
                }
        }
        mb();
@@ -215,6 +227,9 @@ void radeon_gart_restore(struct radeon_device *rdev)
        int i, j, t;
        u64 page_base;
 
+       if (!rdev->gart.ptr) {
+               return;
+       }
        for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) {
                page_base = rdev->gart.pages_addr[i];
                for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
index e6d110ce23314724fdd50f35a29dc61b771caef5..7bb1b079f4806f6d70414809e43e060c1bd1cec2 100644 (file)
@@ -34,7 +34,7 @@
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 {
        u8 out = 0x0;
        u8 buf[8];
@@ -49,15 +49,11 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e
                {
                        .addr = 0x50,
                        .flags = I2C_M_RD,
-                       .len = 1,
+                       .len = 8,
                        .buf = buf,
                }
        };
 
-       /* Read 8 bytes from i2c for extended probe of EDID header */
-       if (requires_extended_probe)
-               msgs[1].len = 8;
-
        /* on hw with routers, select right port */
        if (radeon_connector->router.ddc_valid)
                radeon_router_select_ddc_port(radeon_connector);
@@ -66,17 +62,15 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e
        if (ret != 2)
                /* Couldn't find an accessible DDC on this connector */
                return false;
-       if (requires_extended_probe) {
-               /* Probe also for valid EDID header
-                * EDID header starts with:
-                * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
-                * Only the first 6 bytes must be valid as
-                * drm_edid_block_valid() can fix the last 2 bytes */
-               if (drm_edid_header_is_valid(buf) < 6) {
-                       /* Couldn't find an accessible EDID on this
-                        * connector */
-                       return false;
-               }
+       /* Probe also for valid EDID header
+        * EDID header starts with:
+        * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+        * Only the first 6 bytes must be valid as
+        * drm_edid_block_valid() can fix the last 2 bytes */
+       if (drm_edid_header_is_valid(buf) < 6) {
+               /* Couldn't find an accessible EDID on this
+                * connector */
+               return false;
        }
        return true;
 }
index 9ec830c77af0be7afdba4c9b32f13f1b277bdbe8..8f86aeb266935ef46be2e5dff9022b91c04324c2 100644 (file)
@@ -67,10 +67,10 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
        /* Disable *all* interrupts */
        rdev->irq.sw_int = false;
        rdev->irq.gui_idle = false;
-       for (i = 0; i < rdev->num_crtc; i++)
-               rdev->irq.crtc_vblank_int[i] = false;
-       for (i = 0; i < 6; i++) {
+       for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
                rdev->irq.hpd[i] = false;
+       for (i = 0; i < RADEON_MAX_CRTCS; i++) {
+               rdev->irq.crtc_vblank_int[i] = false;
                rdev->irq.pflip[i] = false;
        }
        radeon_irq_set(rdev);
@@ -99,15 +99,55 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
        /* Disable *all* interrupts */
        rdev->irq.sw_int = false;
        rdev->irq.gui_idle = false;
-       for (i = 0; i < rdev->num_crtc; i++)
-               rdev->irq.crtc_vblank_int[i] = false;
-       for (i = 0; i < 6; i++) {
+       for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
                rdev->irq.hpd[i] = false;
+       for (i = 0; i < RADEON_MAX_CRTCS; i++) {
+               rdev->irq.crtc_vblank_int[i] = false;
                rdev->irq.pflip[i] = false;
        }
        radeon_irq_set(rdev);
 }
 
+static bool radeon_msi_ok(struct radeon_device *rdev)
+{
+       /* RV370/RV380 was first asic with MSI support */
+       if (rdev->family < CHIP_RV380)
+               return false;
+
+       /* MSIs don't work on AGP */
+       if (rdev->flags & RADEON_IS_AGP)
+               return false;
+
+       /* force MSI on */
+       if (radeon_msi == 1)
+               return true;
+       else if (radeon_msi == 0)
+               return false;
+
+       /* Quirks */
+       /* HP RS690 only seems to work with MSIs. */
+       if ((rdev->pdev->device == 0x791f) &&
+           (rdev->pdev->subsystem_vendor == 0x103c) &&
+           (rdev->pdev->subsystem_device == 0x30c2))
+               return true;
+
+       /* Dell RS690 only seems to work with MSIs. */
+       if ((rdev->pdev->device == 0x791f) &&
+           (rdev->pdev->subsystem_vendor == 0x1028) &&
+           (rdev->pdev->subsystem_device == 0x01fd))
+               return true;
+
+       if (rdev->flags & RADEON_IS_IGP) {
+               /* APUs work fine with MSIs */
+               if (rdev->family >= CHIP_PALM)
+                       return true;
+               /* lots of IGPs have problems with MSIs */
+               return false;
+       }
+
+       return true;
+}
+
 int radeon_irq_kms_init(struct radeon_device *rdev)
 {
        int i;
@@ -124,12 +164,8 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
        }
        /* enable msi */
        rdev->msi_enabled = 0;
-       /* MSIs don't seem to work reliably on all IGP
-        * chips.  Disable MSI on them for now.
-        */
-       if ((rdev->family >= CHIP_RV380) &&
-           ((!(rdev->flags & RADEON_IS_IGP)) || (rdev->family >= CHIP_PALM)) &&
-           (!(rdev->flags & RADEON_IS_AGP))) {
+
+       if (radeon_msi_ok(rdev)) {
                int ret = pci_enable_msi(rdev->pdev);
                if (!ret) {
                        rdev->msi_enabled = 1;
index 41a5d48e657b61b7d511977b81ad1c6622e10554..daadf2111040875d93df8fef9752428dd35f1cae 100644 (file)
@@ -991,12 +991,6 @@ static bool radeon_crtc_mode_fixup(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;
-
-       /* adjust pm to upcoming mode change */
-       radeon_pm_compute_clocks(rdev);
-
        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
                return false;
        return true;
index ed0178f0323504dfc5d5ab8be18f6c8026b09dd7..2c2e75ef8a372e1011a37c781e857d8d68c9db50 100644 (file)
@@ -438,9 +438,6 @@ struct radeon_connector {
        struct radeon_i2c_chan *ddc_bus;
        /* some systems have an hdmi and vga port with a shared ddc line */
        bool shared_ddc;
-       /* for some Radeon chip families we apply an additional EDID header
-          check as part of the DDC probe */
-       bool requires_extended_probe;
        bool use_digital;
        /* we need to mind the EDID between detect
           and get modes due to analog/digital/tvencoder */
@@ -459,6 +456,8 @@ struct radeon_framebuffer {
        struct drm_gem_object *obj;
 };
 
+#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
+                               ((em) == ATOM_ENCODER_MODE_DP_MST))
 
 extern enum radeon_tv_std
 radeon_combios_get_tv_info(struct radeon_device *rdev);
@@ -468,8 +467,8 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev);
 extern struct drm_connector *
 radeon_get_connector_for_encoder(struct drm_encoder *encoder);
 
-extern bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder);
-extern bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
+extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
+extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
 extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
 extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
 
@@ -489,7 +488,7 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
                                           int action, uint8_t lane_num,
                                           uint8_t lane_set);
 extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
-extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder);
+extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
 extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                                u8 write_byte, u8 *read_byte);
 
@@ -519,8 +518,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
                                u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
-                       bool requires_extended_probe);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
index 6fabe89fa6a18da11ce5636961b717f84b9b9491..78a665bd95198483862ba0c124453a1d14a87d48 100644 (file)
@@ -53,6 +53,24 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev);
 
 #define ACPI_AC_CLASS           "ac_adapter"
 
+int radeon_pm_get_type_index(struct radeon_device *rdev,
+                            enum radeon_pm_state_type ps_type,
+                            int instance)
+{
+       int i;
+       int found_instance = -1;
+
+       for (i = 0; i < rdev->pm.num_power_states; i++) {
+               if (rdev->pm.power_state[i].type == ps_type) {
+                       found_instance++;
+                       if (found_instance == instance)
+                               return i;
+               }
+       }
+       /* return default if no match */
+       return rdev->pm.default_power_state_index;
+}
+
 #ifdef CONFIG_ACPI
 static int radeon_acpi_event(struct notifier_block *nb,
                             unsigned long val,
index 89a6e1ecea8deb595e8639a459f7aa477e5c287e..06b90c87f8f397012c82d631fa30a5bd57c5da5a 100644 (file)
@@ -77,7 +77,7 @@ int rs400_gart_init(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.ram.ptr) {
+       if (rdev->gart.ptr) {
                WARN(1, "RS400 GART already initialized\n");
                return 0;
        }
@@ -212,6 +212,7 @@ void rs400_gart_fini(struct radeon_device *rdev)
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
        uint32_t entry;
+       u32 *gtt = rdev->gart.ptr;
 
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
@@ -221,7 +222,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
                ((upper_32_bits(addr) & 0xff) << 4) |
                RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
        entry = cpu_to_le32(entry);
-       rdev->gart.table.ram.ptr[i] = entry;
+       gtt[i] = entry;
        return 0;
 }
 
index 9320dd6404f67cdbe9ac3ba20aa6e4e582745904..481b99e89f6542d661c4f0697d413a6eff40f821 100644 (file)
@@ -287,6 +287,7 @@ void rs600_hpd_init(struct radeon_device *rdev)
                default:
                        break;
                }
+               radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
        }
        if (rdev->irq.installed)
                rs600_irq_set(rdev);
@@ -413,7 +414,7 @@ int rs600_gart_init(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.vram.robj) {
+       if (rdev->gart.robj) {
                WARN(1, "RS600 GART already initialized\n");
                return 0;
        }
@@ -431,7 +432,7 @@ static int rs600_gart_enable(struct radeon_device *rdev)
        u32 tmp;
        int r, i;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
@@ -494,20 +495,12 @@ static int rs600_gart_enable(struct radeon_device *rdev)
 void rs600_gart_disable(struct radeon_device *rdev)
 {
        u32 tmp;
-       int r;
 
        /* FIXME: disable out of gart access */
        WREG32_MC(R_000100_MC_PT0_CNTL, 0);
        tmp = RREG32_MC(R_000009_MC_CNTL1);
        WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES);
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (r == 0) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
 }
 
 void rs600_gart_fini(struct radeon_device *rdev)
@@ -525,7 +518,7 @@ void rs600_gart_fini(struct radeon_device *rdev)
 
 int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
-       void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+       void __iomem *ptr = (void *)rdev->gart.ptr;
 
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
index 87cc1feee3ac9e29d10a52cd33d4062342b5cc95..a983f410ab89d7d549530d7b7c2f42287a6a7969 100644 (file)
@@ -124,7 +124,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
        u32 tmp;
        int r, i;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
@@ -171,7 +171,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
 void rv770_pcie_gart_disable(struct radeon_device *rdev)
 {
        u32 tmp;
-       int i, r;
+       int i;
 
        /* Disable all tables */
        for (i = 0; i < 7; i++)
@@ -191,14 +191,7 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev)
        WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
 }
 
 void rv770_pcie_gart_fini(struct radeon_device *rdev)
@@ -282,7 +275,7 @@ static void rv770_mc_program(struct radeon_device *rdev)
                WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
                        rdev->mc.vram_end >> 12);
        }
-       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
        tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
        tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
        WREG32(MC_VM_FB_LOCATION, tmp);
@@ -959,54 +952,6 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
 }
 
-static int rv770_vram_scratch_init(struct radeon_device *rdev)
-{
-       int r;
-       u64 gpu_addr;
-
-       if (rdev->vram_scratch.robj == NULL) {
-               r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
-                                    PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-                                    &rdev->vram_scratch.robj);
-               if (r) {
-                       return r;
-               }
-       }
-
-       r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
-       if (unlikely(r != 0))
-               return r;
-       r = radeon_bo_pin(rdev->vram_scratch.robj,
-                         RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
-       if (r) {
-               radeon_bo_unreserve(rdev->vram_scratch.robj);
-               return r;
-       }
-       r = radeon_bo_kmap(rdev->vram_scratch.robj,
-                               (void **)&rdev->vram_scratch.ptr);
-       if (r)
-               radeon_bo_unpin(rdev->vram_scratch.robj);
-       radeon_bo_unreserve(rdev->vram_scratch.robj);
-
-       return r;
-}
-
-static void rv770_vram_scratch_fini(struct radeon_device *rdev)
-{
-       int r;
-
-       if (rdev->vram_scratch.robj == NULL) {
-               return;
-       }
-       r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
-       if (likely(r == 0)) {
-               radeon_bo_kunmap(rdev->vram_scratch.robj);
-               radeon_bo_unpin(rdev->vram_scratch.robj);
-               radeon_bo_unreserve(rdev->vram_scratch.robj);
-       }
-       radeon_bo_unref(&rdev->vram_scratch.robj);
-}
-
 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
 {
        u64 size_bf, size_af;
@@ -1106,6 +1051,10 @@ static int rv770_startup(struct radeon_device *rdev)
                }
        }
 
+       r = r600_vram_scratch_init(rdev);
+       if (r)
+               return r;
+
        rv770_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                rv770_agp_enable(rdev);
@@ -1114,9 +1063,7 @@ static int rv770_startup(struct radeon_device *rdev)
                if (r)
                        return r;
        }
-       r = rv770_vram_scratch_init(rdev);
-       if (r)
-               return r;
+
        rv770_gpu_init(rdev);
        r = r600_blit_init(rdev);
        if (r) {
@@ -1316,7 +1263,7 @@ void rv770_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        rv770_pcie_gart_fini(rdev);
-       rv770_vram_scratch_fini(rdev);
+       r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_agp_fini(rdev);
index 617b64678fc62f24c70df6ae3fd7ba3bc7d6c9bf..0bb0f5f713e6cf9166a1b91eb19ab81b85206716 100644 (file)
@@ -574,10 +574,16 @@ retry:
                return ret;
 
        spin_lock(&glob->lru_lock);
+
+       if (unlikely(list_empty(&bo->ddestroy))) {
+               spin_unlock(&glob->lru_lock);
+               return 0;
+       }
+
        ret = ttm_bo_reserve_locked(bo, interruptible,
                                    no_wait_reserve, false, 0);
 
-       if (unlikely(ret != 0) || list_empty(&bo->ddestroy)) {
+       if (unlikely(ret != 0)) {
                spin_unlock(&glob->lru_lock);
                return ret;
        }
index 1805b8c2a94817d8d8bac6fa6f5477cb084a9536..dff8fc7671525d347382261402d60d002a21dbb5 100644 (file)
 #define DRM_IOCTL_VMW_PRESENT_READBACK                         \
        DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK,    \
                 struct drm_vmw_present_readback_arg)
+#define DRM_IOCTL_VMW_UPDATE_LAYOUT                            \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,       \
+                struct drm_vmw_update_layout_arg)
 
 /**
  * The core DRM version of this macro doesn't account for
@@ -166,6 +169,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
        VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
                      vmw_present_readback_ioctl,
                      DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
+                     vmw_kms_update_layout_ioctl,
+                     DRM_MASTER | DRM_UNLOCKED),
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
index 30589d0aecd985fd6b556793f4ad8f278f46ad81..8cca91a93bde092af78c6c7bdcfb0ffceb3f04a6 100644 (file)
@@ -40,9 +40,9 @@
 #include "ttm/ttm_module.h"
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20111008"
+#define VMWGFX_DRIVER_DATE "20111025"
 #define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 2
+#define VMWGFX_DRIVER_MINOR 3
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
@@ -633,6 +633,8 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
                     struct drm_vmw_fence_rep __user *user_fence_rep,
                     struct drm_vmw_rect *clips,
                     uint32_t num_clips);
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
 
 /**
  * Overlay control - vmwgfx_overlay.c
index 8b14dfd513a10ece2d9c2fe747e490e08205dd9d..880e285d7578afa3ebeae75de4dad77443d754ce 100644 (file)
@@ -105,12 +105,17 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
        struct vmw_dma_buffer *dmabuf = NULL;
        int ret;
 
+       /* A lot of the code assumes this */
+       if (handle && (width != 64 || height != 64))
+               return -EINVAL;
+
        if (handle) {
                ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
                                                     handle, &surface);
                if (!ret) {
                        if (!surface->snooper.image) {
                                DRM_ERROR("surface not suitable for cursor\n");
+                               vmw_surface_unreference(&surface);
                                return -EINVAL;
                        }
                } else {
@@ -176,7 +181,9 @@ err_unreserve:
                return 0;
        }
 
-       vmw_cursor_update_position(dev_priv, true, du->cursor_x, du->cursor_y);
+       vmw_cursor_update_position(dev_priv, true,
+                                  du->cursor_x + du->hotspot_x,
+                                  du->cursor_y + du->hotspot_y);
 
        return 0;
 }
@@ -191,7 +198,8 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
        du->cursor_y = y + crtc->y;
 
        vmw_cursor_update_position(dev_priv, shown,
-                                  du->cursor_x, du->cursor_y);
+                                  du->cursor_x + du->hotspot_x,
+                                  du->cursor_y + du->hotspot_y);
 
        return 0;
 }
@@ -212,7 +220,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
                SVGA3dCmdHeader header;
                SVGA3dCmdSurfaceDMA dma;
        } *cmd;
-       int ret;
+       int i, ret;
 
        cmd = container_of(header, struct vmw_dma_cmd, header);
 
@@ -234,16 +242,19 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
        box_count = (cmd->header.size - sizeof(SVGA3dCmdSurfaceDMA)) /
                        sizeof(SVGA3dCopyBox);
 
-       if (cmd->dma.guest.pitch != (64 * 4) ||
-           cmd->dma.guest.ptr.offset % PAGE_SIZE ||
+       if (cmd->dma.guest.ptr.offset % PAGE_SIZE ||
            box->x != 0    || box->y != 0    || box->z != 0    ||
            box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
-           box->w != 64   || box->h != 64   || box->d != 1    ||
-           box_count != 1) {
+           box->d != 1    || box_count != 1) {
                /* TODO handle none page aligned offsets */
-               /* TODO handle partial uploads and pitch != 256 */
-               /* TODO handle more then one copy (size != 64) */
-               DRM_ERROR("lazy programmer, can't handle weird stuff\n");
+               /* TODO handle more dst & src != 0 */
+               /* TODO handle more then one copy */
+               DRM_ERROR("Cant snoop dma request for cursor!\n");
+               DRM_ERROR("(%u, %u, %u) (%u, %u, %u) (%ux%ux%u) %u %u\n",
+                         box->srcx, box->srcy, box->srcz,
+                         box->x, box->y, box->z,
+                         box->w, box->h, box->d, box_count,
+                         cmd->dma.guest.ptr.offset);
                return;
        }
 
@@ -262,7 +273,16 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
 
        virtual = ttm_kmap_obj_virtual(&map, &dummy);
 
-       memcpy(srf->snooper.image, virtual, 64*64*4);
+       if (box->w == 64 && cmd->dma.guest.pitch == 64*4) {
+               memcpy(srf->snooper.image, virtual, 64*64*4);
+       } else {
+               /* Image is unsigned pointer. */
+               for (i = 0; i < box->h; i++)
+                       memcpy(srf->snooper.image + i * 64,
+                              virtual + i * cmd->dma.guest.pitch,
+                              box->w * 4);
+       }
+
        srf->snooper.age++;
 
        /* we can't call this function from this function since execbuf has
@@ -394,8 +414,9 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
        top = clips->y1;
        bottom = clips->y2;
 
-       clips_ptr = clips;
-       for (i = 1; i < num_clips; i++, clips_ptr += inc) {
+       /* skip the first clip rect */
+       for (i = 1, clips_ptr = clips + inc;
+            i < num_clips; i++, clips_ptr += inc) {
                left = min_t(int, left, (int)clips_ptr->x1);
                right = max_t(int, right, (int)clips_ptr->x2);
                top = min_t(int, top, (int)clips_ptr->y1);
@@ -994,7 +1015,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
        required_size = mode_cmd->pitch * mode_cmd->height;
        if (unlikely(required_size > (u64) dev_priv->vram_size)) {
                DRM_ERROR("VRAM size is too small for requested mode.\n");
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        /*
@@ -1307,7 +1328,10 @@ int vmw_kms_close(struct vmw_private *dev_priv)
         * drm_encoder_cleanup which takes the lock we deadlock.
         */
        drm_mode_config_cleanup(dev_priv->dev);
-       vmw_kms_close_legacy_display_system(dev_priv);
+       if (dev_priv->sou_priv)
+               vmw_kms_close_screen_object_display(dev_priv);
+       else
+               vmw_kms_close_legacy_display_system(dev_priv);
        return 0;
 }
 
@@ -1517,6 +1541,8 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
                        du->pref_width = rects[du->unit].w;
                        du->pref_height = rects[du->unit].h;
                        du->pref_active = true;
+                       du->gui_x = rects[du->unit].x;
+                       du->gui_y = rects[du->unit].y;
                } else {
                        du->pref_width = 800;
                        du->pref_height = 600;
@@ -1572,12 +1598,14 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force)
        uint32_t num_displays;
        struct drm_device *dev = connector->dev;
        struct vmw_private *dev_priv = vmw_priv(dev);
+       struct vmw_display_unit *du = vmw_connector_to_du(connector);
 
        mutex_lock(&dev_priv->hw_mutex);
        num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
        mutex_unlock(&dev_priv->hw_mutex);
 
-       return ((vmw_connector_to_du(connector)->unit < num_displays) ?
+       return ((vmw_connector_to_du(connector)->unit < num_displays &&
+                du->pref_active) ?
                connector_status_connected : connector_status_disconnected);
 }
 
@@ -1658,6 +1686,28 @@ static struct drm_display_mode vmw_kms_connector_builtin[] = {
        { DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
 };
 
+/**
+ * vmw_guess_mode_timing - Provide fake timings for a
+ * 60Hz vrefresh mode.
+ *
+ * @mode - Pointer to a struct drm_display_mode with hdisplay and vdisplay
+ * members filled in.
+ */
+static void vmw_guess_mode_timing(struct drm_display_mode *mode)
+{
+       mode->hsync_start = mode->hdisplay + 50;
+       mode->hsync_end = mode->hsync_start + 50;
+       mode->htotal = mode->hsync_end + 50;
+
+       mode->vsync_start = mode->vdisplay + 50;
+       mode->vsync_end = mode->vsync_start + 50;
+       mode->vtotal = mode->vsync_end + 50;
+
+       mode->clock = (u32)mode->htotal * (u32)mode->vtotal / 100 * 6;
+       mode->vrefresh = drm_mode_vrefresh(mode);
+}
+
+
 int vmw_du_connector_fill_modes(struct drm_connector *connector,
                                uint32_t max_width, uint32_t max_height)
 {
@@ -1680,18 +1730,23 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
                        return 0;
                mode->hdisplay = du->pref_width;
                mode->vdisplay = du->pref_height;
-               mode->vrefresh = drm_mode_vrefresh(mode);
+               vmw_guess_mode_timing(mode);
+
                if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
                                               mode->vdisplay)) {
                        drm_mode_probed_add(connector, mode);
+               } else {
+                       drm_mode_destroy(dev, mode);
+                       mode = NULL;
+               }
 
-                       if (du->pref_mode) {
-                               list_del_init(&du->pref_mode->head);
-                               drm_mode_destroy(dev, du->pref_mode);
-                       }
-
-                       du->pref_mode = mode;
+               if (du->pref_mode) {
+                       list_del_init(&du->pref_mode->head);
+                       drm_mode_destroy(dev, du->pref_mode);
                }
+
+               /* mode might be null here, this is intended */
+               du->pref_mode = mode;
        }
 
        for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) {
@@ -1712,6 +1767,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
                drm_mode_probed_add(connector, mode);
        }
 
+       /* Move the prefered mode first, help apps pick the right mode. */
+       if (du->pref_mode)
+               list_move(&du->pref_mode->head, &connector->probed_modes);
+
        drm_mode_connector_list_update(connector);
 
        return 1;
@@ -1723,3 +1782,63 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
 {
        return 0;
 }
+
+
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct drm_vmw_update_layout_arg *arg =
+               (struct drm_vmw_update_layout_arg *)data;
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       void __user *user_rects;
+       struct drm_vmw_rect *rects;
+       unsigned rects_size;
+       int ret;
+       int i;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (!arg->num_outputs) {
+               struct drm_vmw_rect def_rect = {0, 0, 800, 600};
+               vmw_du_update_layout(dev_priv, 1, &def_rect);
+               goto out_unlock;
+       }
+
+       rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
+       rects = kzalloc(rects_size, GFP_KERNEL);
+       if (unlikely(!rects)) {
+               ret = -ENOMEM;
+               goto out_unlock;
+       }
+
+       user_rects = (void __user *)(unsigned long)arg->rects;
+       ret = copy_from_user(rects, user_rects, rects_size);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to get rects.\n");
+               ret = -EFAULT;
+               goto out_free;
+       }
+
+       for (i = 0; i < arg->num_outputs; ++i) {
+               if (rects->x < 0 ||
+                   rects->y < 0 ||
+                   rects->x + rects->w > mode_config->max_width ||
+                   rects->y + rects->h > mode_config->max_height) {
+                       DRM_ERROR("Invalid GUI layout.\n");
+                       ret = -EINVAL;
+                       goto out_free;
+               }
+       }
+
+       vmw_du_update_layout(dev_priv, arg->num_outputs, rects);
+
+out_free:
+       kfree(rects);
+out_unlock:
+       ttm_read_unlock(&vmaster->lock);
+       return ret;
+}
index db0b901f8c3f0f05a76117b92768e7a49a1ba24d..af8e6e5bd964a2dca37f7ba17165256d44a2f8bf 100644 (file)
@@ -96,6 +96,13 @@ struct vmw_display_unit {
        unsigned pref_height;
        bool pref_active;
        struct drm_display_mode *pref_mode;
+
+       /*
+        * Gui positioning
+        */
+       int gui_x;
+       int gui_y;
+       bool is_implicit;
 };
 
 #define vmw_crtc_to_du(x) \
@@ -126,8 +133,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
 int vmw_du_connector_set_property(struct drm_connector *connector,
                                  struct drm_property *property,
                                  uint64_t val);
-int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
-                        struct drm_vmw_rect *rects);
+
 
 /*
  * Legacy display unit functions - vmwgfx_ldu.c
index 92f56bc594eb6bcd1f691fc7218316334f9c29ce..90c5e39284913353f68c6e4611d59391d557228c 100644 (file)
@@ -337,13 +337,14 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
        ldu->base.pref_width = 800;
        ldu->base.pref_height = 600;
        ldu->base.pref_mode = NULL;
+       ldu->base.is_implicit = true;
 
        drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
-                          DRM_MODE_CONNECTOR_LVDS);
+                          DRM_MODE_CONNECTOR_VIRTUAL);
        connector->status = vmw_du_connector_detect(connector, true);
 
        drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
-                        DRM_MODE_ENCODER_LVDS);
+                        DRM_MODE_ENCODER_VIRTUAL);
        drm_mode_connector_attach_encoder(connector, encoder);
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
index 477b2a9eb3c2acdc8ebbfcc3a52eb4991bc8f332..4defdcf1c72e2023eaf23f8598c0b83f2803b289 100644 (file)
        container_of(x, struct vmw_screen_object_unit, base.connector)
 
 struct vmw_screen_object_display {
-       struct list_head active;
+       unsigned num_implicit;
 
-       unsigned num_active;
-       unsigned last_num_active;
-
-       struct vmw_framebuffer *fb;
+       struct vmw_framebuffer *implicit_fb;
 };
 
 /**
@@ -54,13 +51,11 @@ struct vmw_screen_object_unit {
        struct vmw_dma_buffer *buffer; /**< Backing store buffer */
 
        bool defined;
-
-       struct list_head active;
+       bool active_implicit;
 };
 
 static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
 {
-       list_del_init(&sou->active);
        vmw_display_unit_cleanup(&sou->base);
        kfree(sou);
 }
@@ -75,58 +70,31 @@ static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
        vmw_sou_destroy(vmw_crtc_to_sou(crtc));
 }
 
-static int vmw_sou_del_active(struct vmw_private *vmw_priv,
+static void vmw_sou_del_active(struct vmw_private *vmw_priv,
                              struct vmw_screen_object_unit *sou)
 {
        struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
-       if (list_empty(&sou->active))
-               return 0;
 
-       /* Must init otherwise list_empty(&sou->active) will not work. */
-       list_del_init(&sou->active);
-       if (--(ld->num_active) == 0) {
-               BUG_ON(!ld->fb);
-               if (ld->fb->unpin)
-                       ld->fb->unpin(ld->fb);
-               ld->fb = NULL;
+       if (sou->active_implicit) {
+               if (--(ld->num_implicit) == 0)
+                       ld->implicit_fb = NULL;
+               sou->active_implicit = false;
        }
-
-       return 0;
 }
 
-static int vmw_sou_add_active(struct vmw_private *vmw_priv,
+static void vmw_sou_add_active(struct vmw_private *vmw_priv,
                              struct vmw_screen_object_unit *sou,
                              struct vmw_framebuffer *vfb)
 {
        struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
-       struct vmw_screen_object_unit *entry;
-       struct list_head *at;
-
-       BUG_ON(!ld->num_active && ld->fb);
-       if (vfb != ld->fb) {
-               if (ld->fb && ld->fb->unpin)
-                       ld->fb->unpin(ld->fb);
-               if (vfb->pin)
-                       vfb->pin(vfb);
-               ld->fb = vfb;
-       }
-
-       if (!list_empty(&sou->active))
-               return 0;
 
-       at = &ld->active;
-       list_for_each_entry(entry, &ld->active, active) {
-               if (entry->base.unit > sou->base.unit)
-                       break;
+       BUG_ON(!ld->num_implicit && ld->implicit_fb);
 
-               at = &entry->active;
+       if (!sou->active_implicit && sou->base.is_implicit) {
+               ld->implicit_fb = vfb;
+               sou->active_implicit = true;
+               ld->num_implicit++;
        }
-
-       list_add(&sou->active, at);
-
-       ld->num_active++;
-
-       return 0;
 }
 
 /**
@@ -164,8 +132,13 @@ static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
                (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
        cmd->obj.size.width = mode->hdisplay;
        cmd->obj.size.height = mode->vdisplay;
-       cmd->obj.root.x = x;
-       cmd->obj.root.y = y;
+       if (sou->base.is_implicit) {
+               cmd->obj.root.x = x;
+               cmd->obj.root.y = y;
+       } else {
+               cmd->obj.root.x = sou->base.gui_x;
+               cmd->obj.root.y = sou->base.gui_y;
+       }
 
        /* Ok to assume that buffer is pinned in vram */
        vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
@@ -312,10 +285,11 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
        }
 
        /* sou only supports one fb active at the time */
-       if (dev_priv->sou_priv->fb && vfb &&
-           !(dev_priv->sou_priv->num_active == 1 &&
-             !list_empty(&sou->active)) &&
-           dev_priv->sou_priv->fb != vfb) {
+       if (sou->base.is_implicit &&
+           dev_priv->sou_priv->implicit_fb && vfb &&
+           !(dev_priv->sou_priv->num_implicit == 1 &&
+             sou->active_implicit) &&
+           dev_priv->sou_priv->implicit_fb != vfb) {
                DRM_ERROR("Multiple framebuffers not supported\n");
                return -EINVAL;
        }
@@ -471,19 +445,20 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
        encoder = &sou->base.encoder;
        connector = &sou->base.connector;
 
-       INIT_LIST_HEAD(&sou->active);
+       sou->active_implicit = false;
 
        sou->base.pref_active = (unit == 0);
        sou->base.pref_width = 800;
        sou->base.pref_height = 600;
        sou->base.pref_mode = NULL;
+       sou->base.is_implicit = true;
 
        drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
-                          DRM_MODE_CONNECTOR_LVDS);
+                          DRM_MODE_CONNECTOR_VIRTUAL);
        connector->status = vmw_du_connector_detect(connector, true);
 
        drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
-                        DRM_MODE_ENCODER_LVDS);
+                        DRM_MODE_ENCODER_VIRTUAL);
        drm_mode_connector_attach_encoder(connector, encoder);
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
@@ -520,10 +495,8 @@ int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv)
        if (unlikely(!dev_priv->sou_priv))
                goto err_no_mem;
 
-       INIT_LIST_HEAD(&dev_priv->sou_priv->active);
-       dev_priv->sou_priv->num_active = 0;
-       dev_priv->sou_priv->last_num_active = 0;
-       dev_priv->sou_priv->fb = NULL;
+       dev_priv->sou_priv->num_implicit = 0;
+       dev_priv->sou_priv->implicit_fb = NULL;
 
        ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
        if (unlikely(ret != 0))
@@ -558,9 +531,6 @@ int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv)
 
        drm_vblank_cleanup(dev);
 
-       if (!list_empty(&dev_priv->sou_priv->active))
-               DRM_ERROR("Still have active outputs when unloading driver");
-
        kfree(dev_priv->sou_priv);
 
        return 0;
index c72f1c0b5e637951a450b21378f2edfeb8e92725..111d956d8e7d0d919d088405ddeaf3b341c87092 100644 (file)
@@ -465,31 +465,29 @@ static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
        while (new_bus) {
                new_bridge = new_bus->self;
 
-               if (new_bridge) {
-                       /* go through list of devices already registered */
-                       list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
-                               bus = same_bridge_vgadev->pdev->bus;
-                               bridge = bus->self;
-
-                               /* see if the share a bridge with this device */
-                               if (new_bridge == bridge) {
-                                       /* if their direct parent bridge is the same
-                                          as any bridge of this device then it can't be used
-                                          for that device */
-                                       same_bridge_vgadev->bridge_has_one_vga = false;
-                               }
+               /* go through list of devices already registered */
+               list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
+                       bus = same_bridge_vgadev->pdev->bus;
+                       bridge = bus->self;
+
+                       /* see if the share a bridge with this device */
+                       if (new_bridge == bridge) {
+                               /* if their direct parent bridge is the same
+                                  as any bridge of this device then it can't be used
+                                  for that device */
+                               same_bridge_vgadev->bridge_has_one_vga = false;
+                       }
 
-                               /* now iterate the previous devices bridge hierarchy */
-                               /* if the new devices parent bridge is in the other devices
-                                  hierarchy then we can't use it to control this device */
-                               while (bus) {
-                                       bridge = bus->self;
-                                       if (bridge) {
-                                               if (bridge == vgadev->pdev->bus->self)
-                                                       vgadev->bridge_has_one_vga = false;
-                                       }
-                                       bus = bus->parent;
+                       /* now iterate the previous devices bridge hierarchy */
+                       /* if the new devices parent bridge is in the other devices
+                          hierarchy then we can't use it to control this device */
+                       while (bus) {
+                               bridge = bus->self;
+                               if (bridge) {
+                                       if (bridge == vgadev->pdev->bus->self)
+                                               vgadev->bridge_has_one_vga = false;
                                }
+                               bus = bus->parent;
                        }
                }
                new_bus = new_bus->parent;
@@ -993,14 +991,20 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                                uc = &priv->cards[i];
                }
 
-               if (!uc)
-                       return -EINVAL;
+               if (!uc) {
+                       ret_val = -EINVAL;
+                       goto done;
+               }
 
-               if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0)
-                       return -EINVAL;
+               if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) {
+                       ret_val = -EINVAL;
+                       goto done;
+               }
 
-               if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0)
-                       return -EINVAL;
+               if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) {
+                       ret_val = -EINVAL;
+                       goto done;
+               }
 
                vga_put(pdev, io_state);
 
index 9ec854ae118b91c5fea647d61bab7f29117a10a5..91be41f6080947936bdd355f25500397ecfd1dfe 100644 (file)
@@ -315,7 +315,7 @@ config SENSORS_DS1621
 
 config SENSORS_EXYNOS4_TMU
        tristate "Temperature sensor on Samsung EXYNOS4"
-       depends on EXYNOS4_DEV_TMU
+       depends on ARCH_EXYNOS4
        help
          If you say yes here you get support for TMU (Thermal Managment
          Unit) on SAMSUNG EXYNOS4 series of SoC.
index 318e38e853764eeeea220bfb519079cf20f687bc..5d760f3d21c2d61ee85227ab7107bf4c38e011f9 100644 (file)
@@ -160,7 +160,6 @@ MODULE_DEVICE_TABLE(spi, ad7314_id);
 static struct spi_driver ad7314_driver = {
        .driver = {
                .name = "ad7314",
-               .bus = &spi_bus_type,
                .owner = THIS_MODULE,
        },
        .probe = ad7314_probe,
index 52319340e182da8f189eae518d80bd3674d26425..04450f8bf5da28e4dff56e70ab86e294920c2cf2 100644 (file)
@@ -227,7 +227,6 @@ static int __devexit ads7871_remove(struct spi_device *spi)
 static struct spi_driver ads7871_driver = {
        .driver = {
                .name = DEVICE_NAME,
-               .bus = &spi_bus_type,
                .owner = THIS_MODULE,
        },
 
index faa0884f61f67bc49e72e93c075160d46078cba4..f2359a0093bd65e52c6985e6a06eef3a0cec8d37 100644 (file)
@@ -506,17 +506,7 @@ static struct platform_driver exynos4_tmu_driver = {
        .resume = exynos4_tmu_resume,
 };
 
-static int __init exynos4_tmu_driver_init(void)
-{
-       return platform_driver_register(&exynos4_tmu_driver);
-}
-module_init(exynos4_tmu_driver_init);
-
-static void __exit exynos4_tmu_driver_exit(void)
-{
-       platform_driver_unregister(&exynos4_tmu_driver);
-}
-module_exit(exynos4_tmu_driver_exit);
+module_platform_driver(exynos4_tmu_driver);
 
 MODULE_DESCRIPTION("EXYNOS4 TMU Driver");
 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
index 89aa9fb743af07260c8deadbc8956eb4c1ada2de..9ba38f318ffb458247dd66b58b77c3c03e203727 100644 (file)
@@ -539,18 +539,7 @@ static struct platform_driver gpio_fan_driver = {
        },
 };
 
-static int __init gpio_fan_init(void)
-{
-       return platform_driver_register(&gpio_fan_driver);
-}
-
-static void __exit gpio_fan_exit(void)
-{
-       platform_driver_unregister(&gpio_fan_driver);
-}
-
-module_init(gpio_fan_init);
-module_exit(gpio_fan_exit);
+module_platform_driver(gpio_fan_driver);
 
 MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
 MODULE_DESCRIPTION("GPIO FAN driver");
index fea292d43407cecba6e75b70021617f871d6b1b8..7a48b1eb423334780116f1cb6e16edcec8f19a49 100644 (file)
@@ -212,17 +212,7 @@ struct platform_driver jz4740_hwmon_driver = {
        },
 };
 
-static int __init jz4740_hwmon_init(void)
-{
-       return platform_driver_register(&jz4740_hwmon_driver);
-}
-module_init(jz4740_hwmon_init);
-
-static void __exit jz4740_hwmon_exit(void)
-{
-       platform_driver_unregister(&jz4740_hwmon_driver);
-}
-module_exit(jz4740_hwmon_exit);
+module_platform_driver(jz4740_hwmon_driver);
 
 MODULE_DESCRIPTION("JZ4740 SoC HWMON driver");
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
index eab11615dced6b54e71996bfd4df60c159bbe570..9b382ec2c3bd4de978d98a6d9f24f797684fe534 100644 (file)
@@ -432,19 +432,7 @@ static struct platform_driver ntc_thermistor_driver = {
        .id_table = ntc_thermistor_id,
 };
 
-static int __init ntc_thermistor_init(void)
-{
-       return platform_driver_register(&ntc_thermistor_driver);
-}
-
-module_init(ntc_thermistor_init);
-
-static void __exit ntc_thermistor_cleanup(void)
-{
-       platform_driver_unregister(&ntc_thermistor_driver);
-}
-
-module_exit(ntc_thermistor_cleanup);
+module_platform_driver(ntc_thermistor_driver);
 
 MODULE_DESCRIPTION("NTC Thermistor Driver");
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
index b39f52e2752a7bca54a1bb25c7083382b01aa52e..f6c26d19f521aaa98dd2b0596d67ab27028b8d15 100644 (file)
@@ -393,18 +393,7 @@ static struct platform_driver s3c_hwmon_driver = {
        .remove         = __devexit_p(s3c_hwmon_remove),
 };
 
-static int __init s3c_hwmon_init(void)
-{
-       return platform_driver_register(&s3c_hwmon_driver);
-}
-
-static void __exit s3c_hwmon_exit(void)
-{
-       platform_driver_unregister(&s3c_hwmon_driver);
-}
-
-module_init(s3c_hwmon_init);
-module_exit(s3c_hwmon_exit);
+module_platform_driver(s3c_hwmon_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C ADC HWMon driver");
index e3b5c6039c2541e67e63066e4311f2dc6c1021b6..79b6dabe3161461a3f1ccdf277588860f7863df9 100644 (file)
@@ -590,19 +590,8 @@ static struct platform_driver sch5627_driver = {
        .remove         = sch5627_remove,
 };
 
-static int __init sch5627_init(void)
-{
-       return platform_driver_register(&sch5627_driver);
-}
-
-static void __exit sch5627_exit(void)
-{
-       platform_driver_unregister(&sch5627_driver);
-}
+module_platform_driver(sch5627_driver);
 
 MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
-
-module_init(sch5627_init);
-module_exit(sch5627_exit);
index 244407aa79fcbe05dc05b10ae7d88c0327db6d29..9d5236fb09b421e6a1e78cd5b190eaa9d19f6a2d 100644 (file)
@@ -521,19 +521,8 @@ static struct platform_driver sch5636_driver = {
        .remove         = sch5636_remove,
 };
 
-static int __init sch5636_init(void)
-{
-       return platform_driver_register(&sch5636_driver);
-}
-
-static void __exit sch5636_exit(void)
-{
-       platform_driver_unregister(&sch5636_driver);
-}
+module_platform_driver(sch5636_driver);
 
 MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
-
-module_init(sch5636_init);
-module_exit(sch5636_exit);
index 57240740b161d190329b5ca3b7dfaf0d049ef02e..0018c7dd0097de5045f646d98e715713ea7edba4 100644 (file)
@@ -136,19 +136,7 @@ static struct platform_driver twl4030_madc_hwmon_driver = {
                   },
 };
 
-static int __init twl4030_madc_hwmon_init(void)
-{
-       return platform_driver_register(&twl4030_madc_hwmon_driver);
-}
-
-module_init(twl4030_madc_hwmon_init);
-
-static void __exit twl4030_madc_hwmon_exit(void)
-{
-       platform_driver_unregister(&twl4030_madc_hwmon_driver);
-}
-
-module_exit(twl4030_madc_hwmon_exit);
+module_platform_driver(twl4030_madc_hwmon_driver);
 
 MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver");
 MODULE_LICENSE("GPL");
index 3cd07bf42dca4203c93712823fdf3dd2fb3335fa..b9a87e89bab4471ce29aba1509f14bd908603b3e 100644 (file)
@@ -309,15 +309,4 @@ static struct platform_driver env_driver = {
        .remove         = __devexit_p(env_remove),
 };
 
-static int __init env_init(void)
-{
-       return platform_driver_register(&env_driver);
-}
-
-static void __exit env_exit(void)
-{
-       platform_driver_unregister(&env_driver);
-}
-
-module_init(env_init);
-module_exit(env_exit);
+module_platform_driver(env_driver);
index 97b1f834a4714b540fd95352271bb253ef130c9c..9b598ed26020563978f1142840c4b6a5f0ecad77 100644 (file)
@@ -209,17 +209,7 @@ static struct platform_driver wm831x_hwmon_driver = {
        },
 };
 
-static int __init wm831x_hwmon_init(void)
-{
-       return platform_driver_register(&wm831x_hwmon_driver);
-}
-module_init(wm831x_hwmon_init);
-
-static void __exit wm831x_hwmon_exit(void)
-{
-       platform_driver_unregister(&wm831x_hwmon_driver);
-}
-module_exit(wm831x_hwmon_exit);
+module_platform_driver(wm831x_hwmon_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM831x Hardware Monitoring");
index 13290595ca8660f25ebbd0e0c350795dc3d6ccc8..3ff67edbdc44af02a7d0553dd2d74530cc00ca6f 100644 (file)
@@ -133,17 +133,7 @@ static struct platform_driver wm8350_hwmon_driver = {
        },
 };
 
-static int __init wm8350_hwmon_init(void)
-{
-       return platform_driver_register(&wm8350_hwmon_driver);
-}
-module_init(wm8350_hwmon_init);
-
-static void __exit wm8350_hwmon_exit(void)
-{
-       platform_driver_unregister(&wm8350_hwmon_driver);
-}
-module_exit(wm8350_hwmon_exit);
+module_platform_driver(wm8350_hwmon_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM8350 Hardware Monitoring");
index 143461a95ae4adc8bd75557aa8e76f5a2d298b9f..86980fe041179e388007bb042dfde84a667acf59 100644 (file)
@@ -21,6 +21,7 @@
  * General Public License for more details.
  */
 
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
@@ -108,10 +109,8 @@ static int __devinit u8500_hsem_probe(struct platform_device *pdev)
                return -ENODEV;
 
        io_base = ioremap(res->start, resource_size(res));
-       if (!io_base) {
-               ret = -ENOMEM;
-               goto free_state;
-       }
+       if (!io_base)
+               return -ENOMEM;
 
        /* make sure protocol 1 is selected */
        val = readl(io_base + HSEM_CTRL_REG);
index 85584a547c25201a1375bf92b074af571d37be0e..525c7345fa0b904242a0ef10a5d9502ab5e4baf1 100644 (file)
@@ -488,7 +488,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 
        if (flags & I2C_M_TEN) {
                /* a ten bit address */
-               addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+               addr = 0xf0 | ((msg->addr >> 7) & 0x06);
                bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
                /* try extended address code...*/
                ret = try_address(i2c_adap, addr, retries);
@@ -498,7 +498,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
                        return -ENXIO;
                }
                /* the remaining 8 bit address */
-               ret = i2c_outb(i2c_adap, msg->addr & 0x7f);
+               ret = i2c_outb(i2c_adap, msg->addr & 0xff);
                if ((ret != 1) && !nak_ok) {
                        /* the chip did not ack / xmission error occurred */
                        dev_err(&i2c_adap->dev, "died at 2nd address code\n");
index 835e47b39bc264535c567669d12a81784a8c90c7..03b61577888748a4d9a61cfe46b413eaaa219737 100644 (file)
@@ -593,7 +593,7 @@ static int __devinit nuc900_i2c_probe(struct platform_device *pdev)
        i2c->adap.algo_data = i2c;
        i2c->adap.dev.parent = &pdev->dev;
 
-       mfp_set_groupg(&pdev->dev);
+       mfp_set_groupg(&pdev->dev, NULL);
 
        clk_get_rate(i2c->clk);
 
index 131079a3e2923a1feaa05248a236d8ee27890c4a..1e5606185b4f581939d6da4334b36747e90c35ba 100644 (file)
@@ -539,8 +539,10 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
        client->dev.type = &i2c_client_type;
        client->dev.of_node = info->of_node;
 
+       /* For 10-bit clients, add an arbitrary offset to avoid collisions */
        dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
-                    client->addr);
+                    client->addr | ((client->flags & I2C_CLIENT_TEN)
+                                    ? 0xa000 : 0));
        status = device_register(&client->dev);
        if (status)
                goto out_err;
index c90ce50b619f7b483b85483a24457a8cab73f3c2..57a45ce84b2d42f893cf45fb6e876bc1904bcfde 100644 (file)
@@ -579,7 +579,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
        return 0;
 }
 
-int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
+static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
                         void *data)
 {
        struct device *dev = data;
index 67cbcfa351225b4f7c60dce041562a411d76430e..847553fd8b963beca810aadb548d2f4f96db666e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
  *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
- *  Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2007-2011 Bartlomiej Zolnierkiewicz
  *
  * CYPRESS CY82C693 chipset IDE controller
  *
@@ -90,7 +90,7 @@ static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
        u8 time_16, time_8;
 
        /* select primary or secondary channel */
-       if (hwif->index > 0) {  /* drive is on the secondary channel */
+       if (drive->dn > 1) {  /* drive is on the secondary channel */
                dev = pci_get_slot(dev->bus, dev->devfn+1);
                if (!dev) {
                        printk(KERN_ERR "%s: tune_drive: "
@@ -141,7 +141,7 @@ static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
                pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
                pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
        }
-       if (hwif->index > 0)
+       if (drive->dn > 1)
                pci_dev_put(dev);
 }
 
index 4a697a238e280e2ce14c627d0d1f4bf053b86b45..8716066a2f2b79c1ddeb1236a9b2091d7bd62f63 100644 (file)
@@ -521,8 +521,8 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
        if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
                d.init_dma = icside_dma_init;
                d.port_ops = &icside_v6_port_ops;
+       } else
                d.dma_ops = NULL;
-       }
 
        ret = ide_host_register(host, &d, hws);
        if (ret)
index 04b09564bfa902bf84f6a313594112e74a1db2c6..8126824daccba7726b637ef1358b80cfa3b49468 100644 (file)
@@ -43,7 +43,6 @@
 /* For SCSI -> ATAPI command conversion */
 #include <scsi/scsi.h>
 
-#include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/byteorder.h>
 #include <linux/uaccess.h>
index 61fdf544fbd63193926010ff33fef34f9d30dbe9..3d42043fec51ee1bf86d204912da85b57242f1e5 100644 (file)
@@ -35,7 +35,6 @@
 #include <scsi/scsi_ioctl.h>
 
 #include <asm/byteorder.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/unaligned.h>
index 7ecb1ade8874b86c293a5d1a4a2a59ffc7efc860..ce8237d361596840cb679c6f41dbd89bb0ad7d48 100644 (file)
@@ -41,7 +41,6 @@
 #include <scsi/scsi.h>
 
 #include <asm/byteorder.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/unaligned.h>
index b59d04c720517d722633f9feef63a42505f86625..1892e81fb00f615b80c3dfaa8f10a643037a5eb6 100644 (file)
@@ -331,7 +331,7 @@ static const struct ide_port_ops ich_port_ops = {
                .udma_mask      = udma,                 \
        }
 
-#define DECLARE_ICH_DEV(udma) \
+#define DECLARE_ICH_DEV(mwdma, udma) \
        { \
                .name           = DRV_NAME, \
                .init_chipset   = init_chipset_ich, \
@@ -340,7 +340,7 @@ static const struct ide_port_ops ich_port_ops = {
                .port_ops       = &ich_port_ops, \
                .pio_mask       = ATA_PIO4, \
                .swdma_mask     = ATA_SWDMA2_ONLY, \
-               .mwdma_mask     = ATA_MWDMA12_ONLY, \
+               .mwdma_mask     = mwdma, \
                .udma_mask      = udma, \
        }
 
@@ -362,13 +362,15 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = {
        /* 2: PIIX4 */
        DECLARE_PIIX_DEV(ATA_UDMA2),
        /* 3: ICH0 */
-       DECLARE_ICH_DEV(ATA_UDMA2),
+       DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA2),
        /* 4: ICH */
-       DECLARE_ICH_DEV(ATA_UDMA4),
+       DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA4),
        /* 5: PIIX4 */
        DECLARE_PIIX_DEV(ATA_UDMA4),
-       /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
-       DECLARE_ICH_DEV(ATA_UDMA5),
+       /* 6: ICH[2-6]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
+       DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA5),
+       /* 7: ICH7/7-R, no MWDMA1 */
+       DECLARE_ICH_DEV(ATA_MWDMA2_ONLY, ATA_UDMA5),
 };
 
 /**
@@ -438,9 +440,9 @@ static const struct pci_device_id piix_pci_tbl[] = {
 #endif
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2),      6 },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19),    6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    7 },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1),  6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    7 },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6),     6 },
        { 0, },
 };
index e53a1b78378b02c414c0c292c954974c763d880d..281c91426345946279412880bc804d01d287ec4c 100644 (file)
@@ -113,12 +113,26 @@ static const struct pci_device_id triflex_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
 
+#ifdef CONFIG_PM
+static int triflex_ide_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       /*
+        * We must not disable or powerdown the device.
+        * APM bios refuses to suspend if IDE is not accessible.
+        */
+       pci_save_state(dev);
+       return 0;
+}
+#else
+#define triflex_ide_pci_suspend NULL
+#endif
+
 static struct pci_driver triflex_pci_driver = {
        .name           = "TRIFLEX_IDE",
        .id_table       = triflex_pci_tbl,
        .probe          = triflex_init_one,
        .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
+       .suspend        = triflex_ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
 
index 18767f8ab090a409c512db7ba29bf4b8d56cb2f2..5d2f8e13cf0e670e83b48b6dc243402d781b9758 100644 (file)
@@ -82,7 +82,8 @@ static unsigned int mwait_substates;
 static unsigned int lapic_timer_reliable_states = (1 << 1);     /* Default to only C1 */
 
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
+static int intel_idle(struct cpuidle_device *dev,
+                       struct cpuidle_driver *drv, int index);
 
 static struct cpuidle_state *cpuidle_state_table;
 
@@ -110,7 +111,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C1 */
                .name = "C1-NHM",
                .desc = "MWAIT 0x00",
-               .driver_data = (void *) 0x00,
                .flags = CPUIDLE_FLAG_TIME_VALID,
                .exit_latency = 3,
                .target_residency = 6,
@@ -118,7 +118,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C2 */
                .name = "C3-NHM",
                .desc = "MWAIT 0x10",
-               .driver_data = (void *) 0x10,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 20,
                .target_residency = 80,
@@ -126,7 +125,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C3 */
                .name = "C6-NHM",
                .desc = "MWAIT 0x20",
-               .driver_data = (void *) 0x20,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 200,
                .target_residency = 800,
@@ -138,7 +136,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C1 */
                .name = "C1-SNB",
                .desc = "MWAIT 0x00",
-               .driver_data = (void *) 0x00,
                .flags = CPUIDLE_FLAG_TIME_VALID,
                .exit_latency = 1,
                .target_residency = 1,
@@ -146,7 +143,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C2 */
                .name = "C3-SNB",
                .desc = "MWAIT 0x10",
-               .driver_data = (void *) 0x10,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 80,
                .target_residency = 211,
@@ -154,7 +150,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C3 */
                .name = "C6-SNB",
                .desc = "MWAIT 0x20",
-               .driver_data = (void *) 0x20,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 104,
                .target_residency = 345,
@@ -162,7 +157,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C4 */
                .name = "C7-SNB",
                .desc = "MWAIT 0x30",
-               .driver_data = (void *) 0x30,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 109,
                .target_residency = 345,
@@ -174,7 +168,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C1 */
                .name = "C1-ATM",
                .desc = "MWAIT 0x00",
-               .driver_data = (void *) 0x00,
                .flags = CPUIDLE_FLAG_TIME_VALID,
                .exit_latency = 1,
                .target_residency = 4,
@@ -182,7 +175,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C2 */
                .name = "C2-ATM",
                .desc = "MWAIT 0x10",
-               .driver_data = (void *) 0x10,
                .flags = CPUIDLE_FLAG_TIME_VALID,
                .exit_latency = 20,
                .target_residency = 80,
@@ -191,7 +183,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C4 */
                .name = "C4-ATM",
                .desc = "MWAIT 0x30",
-               .driver_data = (void *) 0x30,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 100,
                .target_residency = 400,
@@ -200,23 +191,55 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C6 */
                .name = "C6-ATM",
                .desc = "MWAIT 0x52",
-               .driver_data = (void *) 0x52,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 140,
                .target_residency = 560,
                .enter = &intel_idle },
 };
 
+static int get_driver_data(int cstate)
+{
+       int driver_data;
+       switch (cstate) {
+
+       case 1: /* MWAIT C1 */
+               driver_data = 0x00;
+               break;
+       case 2: /* MWAIT C2 */
+               driver_data = 0x10;
+               break;
+       case 3: /* MWAIT C3 */
+               driver_data = 0x20;
+               break;
+       case 4: /* MWAIT C4 */
+               driver_data = 0x30;
+               break;
+       case 5: /* MWAIT C5 */
+               driver_data = 0x40;
+               break;
+       case 6: /* MWAIT C6 */
+               driver_data = 0x52;
+               break;
+       default:
+               driver_data = 0x00;
+       }
+       return driver_data;
+}
+
 /**
  * intel_idle
  * @dev: cpuidle_device
- * @state: cpuidle state
+ * @drv: cpuidle driver
+ * @index: index of cpuidle state
  *
  */
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
+static int intel_idle(struct cpuidle_device *dev,
+               struct cpuidle_driver *drv, int index)
 {
        unsigned long ecx = 1; /* break on interrupt flag */
-       unsigned long eax = (unsigned long)cpuidle_get_statedata(state);
+       struct cpuidle_state *state = &drv->states[index];
+       struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+       unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
        unsigned int cstate;
        ktime_t kt_before, kt_after;
        s64 usec_delta;
@@ -257,7 +280,10 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 
-       return usec_delta;
+       /* Update cpuidle counters */
+       dev->last_residency = (int)usec_delta;
+
+       return index;
 }
 
 static void __setup_broadcast_timer(void *arg)
@@ -397,6 +423,60 @@ static void intel_idle_cpuidle_devices_uninit(void)
        free_percpu(intel_idle_cpuidle_devices);
        return;
 }
+/*
+ * intel_idle_cpuidle_driver_init()
+ * allocate, initialize cpuidle_states
+ */
+static int intel_idle_cpuidle_driver_init(void)
+{
+       int cstate;
+       struct cpuidle_driver *drv = &intel_idle_driver;
+
+       drv->state_count = 1;
+
+       for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
+               int num_substates;
+
+               if (cstate > max_cstate) {
+                       printk(PREFIX "max_cstate %d reached\n",
+                               max_cstate);
+                       break;
+               }
+
+               /* does the state exist in CPUID.MWAIT? */
+               num_substates = (mwait_substates >> ((cstate) * 4))
+                                       & MWAIT_SUBSTATE_MASK;
+               if (num_substates == 0)
+                       continue;
+               /* is the state not enabled? */
+               if (cpuidle_state_table[cstate].enter == NULL) {
+                       /* does the driver not know about the state? */
+                       if (*cpuidle_state_table[cstate].name == '\0')
+                               pr_debug(PREFIX "unaware of model 0x%x"
+                                       " MWAIT %d please"
+                                       " contact lenb@kernel.org",
+                               boot_cpu_data.x86_model, cstate);
+                       continue;
+               }
+
+               if ((cstate > 2) &&
+                       !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+                       mark_tsc_unstable("TSC halts in idle"
+                                       " states deeper than C2");
+
+               drv->states[drv->state_count] = /* structure copy */
+                       cpuidle_state_table[cstate];
+
+               drv->state_count += 1;
+       }
+
+       if (auto_demotion_disable_flags)
+               smp_call_function(auto_demotion_disable, NULL, 1);
+
+       return 0;
+}
+
+
 /*
  * intel_idle_cpuidle_devices_init()
  * allocate, initialize, register cpuidle_devices
@@ -431,22 +511,11 @@ static int intel_idle_cpuidle_devices_init(void)
                                continue;
                        /* is the state not enabled? */
                        if (cpuidle_state_table[cstate].enter == NULL) {
-                               /* does the driver not know about the state? */
-                               if (*cpuidle_state_table[cstate].name == '\0')
-                                       pr_debug(PREFIX "unaware of model 0x%x"
-                                               " MWAIT %d please"
-                                               " contact lenb@kernel.org",
-                                       boot_cpu_data.x86_model, cstate);
                                continue;
                        }
 
-                       if ((cstate > 2) &&
-                               !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
-                               mark_tsc_unstable("TSC halts in idle"
-                                       " states deeper than C2");
-
-                       dev->states[dev->state_count] = /* structure copy */
-                               cpuidle_state_table[cstate];
+                       dev->states_usage[dev->state_count].driver_data =
+                               (void *)get_driver_data(cstate);
 
                        dev->state_count += 1;
                }
@@ -459,8 +528,6 @@ static int intel_idle_cpuidle_devices_init(void)
                        return -EIO;
                }
        }
-       if (auto_demotion_disable_flags)
-               smp_call_function(auto_demotion_disable, NULL, 1);
 
        return 0;
 }
@@ -478,6 +545,7 @@ static int __init intel_idle_init(void)
        if (retval)
                return retval;
 
+       intel_idle_cpuidle_driver_init();
        retval = cpuidle_register_driver(&intel_idle_driver);
        if (retval) {
                printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
index 691276bafd7812c168c4dadbe1aa315bf43bad80..e9cf51b1343ba520d8928367a1eca80f9f531657 100644 (file)
@@ -216,7 +216,9 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 
        neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
        if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+               rcu_read_lock();
                neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
+               rcu_read_unlock();
                ret = -ENODATA;
                if (neigh)
                        goto release;
@@ -274,15 +276,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
                goto put;
        }
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
        if (!neigh || !(neigh->nud_state & NUD_VALID)) {
                if (neigh)
                        neigh_event_send(neigh, NULL);
                ret = -ENODATA;
-               goto put;
+       } else {
+               ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
        }
-
-       ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
+       rcu_read_unlock();
 put:
        dst_release(dst);
        return ret;
index de6d0774e60990f644e39ca815159f68b5a065d1..c88b12beef25be72383f3423894121882d76d009 100644 (file)
@@ -1375,8 +1375,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                goto reject;
        }
        dst = &rt->dst;
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
        l2t = t3_l2t_get(tdev, neigh, neigh->dev);
+       rcu_read_unlock();
        if (!l2t) {
                printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
                       __func__);
@@ -1946,10 +1948,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        }
        ep->dst = &rt->dst;
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(ep->dst);
 
        /* get a l2t entry */
        ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
index b36cdac9c558a35aa78f2061e9f7435dc1504754..0747004313ad5cabdc34a6e206b0fb5d49e25a32 100644 (file)
@@ -542,8 +542,10 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
                     (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
        mpa->private_data_size = htons(ep->plen);
        mpa->revision = mpa_rev_to_use;
-       if (mpa_rev_to_use == 1)
+       if (mpa_rev_to_use == 1) {
                ep->tried_with_mpa_v1 = 1;
+               ep->retry_with_mpa_v1 = 0;
+       }
 
        if (mpa_rev_to_use == 2) {
                mpa->private_data_size +=
@@ -1594,6 +1596,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                goto reject;
        }
        dst = &rt->dst;
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
        if (neigh->dev->flags & IFF_LOOPBACK) {
                pdev = ip_dev_find(&init_net, peer_ip);
@@ -1620,6 +1623,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                rss_qid = dev->rdev.lldi.rxq_ids[
                          cxgb4_port_idx(neigh->dev) * step];
        }
+       rcu_read_unlock();
        if (!l2t) {
                printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
                       __func__);
@@ -1820,6 +1824,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
        }
        ep->dst = &rt->dst;
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(ep->dst);
 
        /* get a l2t entry */
@@ -1856,6 +1861,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
                ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
                        cxgb4_port_idx(neigh->dev) * step];
        }
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
@@ -2301,6 +2307,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        }
        ep->dst = &rt->dst;
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(ep->dst);
 
        /* get a l2t entry */
@@ -2339,6 +2346,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                ep->retry_with_mpa_v1 = 0;
                ep->tried_with_mpa_v1 = 0;
        }
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
index f35a935267e77e7a58c3be85437cbcb1a1f35cb7..0f1607c8325a5bc8a03e3a5d5471d39ed5741e8b 100644 (file)
@@ -311,7 +311,7 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count)
        while (ptr != cq->sw_pidx) {
                cqe = &cq->sw_queue[ptr];
                if (RQ_TYPE(cqe) && (CQE_OPCODE(cqe) != FW_RI_READ_RESP) &&
-                   (CQE_QPID(cqe) == wq->rq.qid) && cqe_completes_wr(cqe, wq))
+                   (CQE_QPID(cqe) == wq->sq.qid) && cqe_completes_wr(cqe, wq))
                        (*count)++;
                if (++ptr == cq->size)
                        ptr = 0;
index dfce9ea98a39b3f0f68e6d152d438554ebe8ee84..0a52d72371ee5f6cf2f938ba81fa0c887fd00070 100644 (file)
@@ -1377,9 +1377,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
                neigh_release(neigh);
        }
 
-       if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
+       if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
+               rcu_read_lock();
                neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
-
+               rcu_read_unlock();
+       }
        ip_rt_put(rt);
        return rc;
 }
index 5bd2162b95dcb8c93051ce7e496b628222764184..1d5895941e193e35e5ff88804fb00a9c29c8a5fa 100644 (file)
@@ -2307,19 +2307,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
                SYM_LSB(IBCCtrlA_0, MaxPktLen);
        ppd->cpspec->ibcctrl_a = ibc; /* without linkcmd or linkinitcmd! */
 
-       /* initially come up waiting for TS1, without sending anything. */
-       val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
-               QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
-
-       ppd->cpspec->ibcctrl_a = val;
        /*
         * Reset the PCS interface to the serdes (and also ibc, which is still
         * in reset from above).  Writes new value of ibcctrl_a as last step.
         */
        qib_7322_mini_pcs_reset(ppd);
-       qib_write_kreg(dd, kr_scratch, 0ULL);
-       /* clear the linkinit cmds */
-       ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
 
        if (!ppd->cpspec->ibcctrl_b) {
                unsigned lse = ppd->link_speed_enabled;
@@ -2385,6 +2377,14 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
        ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
        set_vls(ppd);
 
+       /* initially come up DISABLED, without sending anything. */
+       val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
+                                       QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
+       qib_write_kreg_port(ppd, krp_ibcctrl_a, val);
+       qib_write_kreg(dd, kr_scratch, 0ULL);
+       /* clear the linkinit cmds */
+       ppd->cpspec->ibcctrl_a = val & ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
+
        /* be paranoid against later code motion, etc. */
        spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
        ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable);
@@ -5241,7 +5241,7 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
                           off */
                        if (ppd->dd->flags & QIB_HAS_QSFP) {
                                qd->t_insert = get_jiffies_64();
-                               schedule_work(&qd->work);
+                               queue_work(ib_wq, &qd->work);
                        }
                        spin_lock_irqsave(&ppd->sdma_lock, flags);
                        if (__qib_sdma_running(ppd))
index e06c4ed383f14598674ce8a0847c9780a6231c46..fa71b1e666c5414fbba2357fe531e75cabc7986c 100644 (file)
@@ -480,18 +480,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
        udelay(20); /* Generous RST dwell */
 
        dd->f_gpio_mod(dd, mask, mask, mask);
-       /* Spec says module can take up to two seconds! */
-       mask = QSFP_GPIO_MOD_PRS_N;
-       if (qd->ppd->hw_pidx)
-               mask <<= QSFP_GPIO_PORT2_SHIFT;
-
-       /* Do not try to wait here. Better to let event handle it */
-       if (!qib_qsfp_mod_present(qd->ppd))
-               goto bail;
-       /* We see a module, but it may be unwise to look yet. Just schedule */
-       qd->t_insert = get_jiffies_64();
-       queue_work(ib_wq, &qd->work);
-bail:
        return;
 }
 
index 0ef9af94997dcd5737922aa37a1483491b0c63f1..4115be54ba3b32626dc75c4529a3aa186b6f02c1 100644 (file)
@@ -57,21 +57,24 @@ struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
                                 struct ib_pd *pd, struct ib_ah_attr *attr)
 {
        struct ipoib_ah *ah;
+       struct ib_ah *vah;
 
        ah = kmalloc(sizeof *ah, GFP_KERNEL);
        if (!ah)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        ah->dev       = dev;
        ah->last_send = 0;
        kref_init(&ah->ref);
 
-       ah->ah = ib_create_ah(pd, attr);
-       if (IS_ERR(ah->ah)) {
+       vah = ib_create_ah(pd, attr);
+       if (IS_ERR(vah)) {
                kfree(ah);
-               ah = NULL;
-       } else
+               ah = (struct ipoib_ah *)vah;
+       } else {
+               ah->ah = vah;
                ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah);
+       }
 
        return ah;
 }
index 7567b60002309a19a2d0a4cc13da855a46042be4..83695b48b010a643a9b16d9240fa9a8538fa5d06 100644 (file)
@@ -432,7 +432,7 @@ static void path_rec_completion(int status,
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       if (ah) {
+       if (!IS_ERR_OR_NULL(ah)) {
                path->pathrec = *pathrec;
 
                old_ah   = path->ah;
@@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *dev,
        return 0;
 }
 
+/* called with rcu_read_lock */
 static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -636,6 +637,7 @@ err_drop:
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+/* called with rcu_read_lock */
 static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
@@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct neighbour *n = NULL;
        unsigned long flags;
 
+       rcu_read_lock();
        if (likely(skb_dst(skb)))
                n = dst_get_neighbour(skb_dst(skb));
 
        if (likely(n)) {
                if (unlikely(!*to_ipoib_neigh(n))) {
                        ipoib_path_lookup(skb, dev);
-                       return NETDEV_TX_OK;
+                       goto unlock;
                }
 
                neigh = *to_ipoib_neigh(n);
@@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        ipoib_neigh_free(dev, neigh);
                        spin_unlock_irqrestore(&priv->lock, flags);
                        ipoib_path_lookup(skb, dev);
-                       return NETDEV_TX_OK;
+                       goto unlock;
                }
 
                if (ipoib_cm_get(neigh)) {
                        if (ipoib_cm_up(neigh)) {
                                ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
-                               return NETDEV_TX_OK;
+                               goto unlock;
                        }
                } else if (neigh->ah) {
                        ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
-                       return NETDEV_TX_OK;
+                       goto unlock;
                }
 
                if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
@@ -793,13 +796,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                           phdr->hwaddr + 4);
                                dev_kfree_skb_any(skb);
                                ++dev->stats.tx_dropped;
-                               return NETDEV_TX_OK;
+                               goto unlock;
                        }
 
                        unicast_arp_send(skb, dev, phdr);
                }
        }
-
+unlock:
+       rcu_read_unlock();
        return NETDEV_TX_OK;
 }
 
@@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
        dst = skb_dst(skb);
        n = NULL;
        if (dst)
-               n = dst_get_neighbour(dst);
+               n = dst_get_neighbour_raw(dst);
        if ((!dst || !n) && daddr) {
                struct ipoib_pseudoheader *phdr =
                        (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
index 1b7a9768635673f1a78f74e54e9e33fd37a80eb7..873bff97e69e266f6c39624f5fe3319eb76f7aae 100644 (file)
@@ -240,8 +240,11 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
                av.grh.dgid = mcast->mcmember.mgid;
 
                ah = ipoib_create_ah(dev, priv->pd, &av);
-               if (!ah) {
-                       ipoib_warn(priv, "ib_address_create failed\n");
+               if (IS_ERR(ah)) {
+                       ipoib_warn(priv, "ib_address_create failed %ld\n",
+                               -PTR_ERR(ah));
+                       /* use original error */
+                       return PTR_ERR(ah);
                } else {
                        spin_lock_irq(&priv->lock);
                        mcast->ah = ah;
@@ -266,7 +269,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
 
                skb->dev = dev;
                if (dst)
-                       n = dst_get_neighbour(dst);
+                       n = dst_get_neighbour_raw(dst);
                if (!dst || !n) {
                        /* put pseudoheader back on for next time */
                        skb_push(skb, sizeof (struct ipoib_pseudoheader));
@@ -722,6 +725,8 @@ out:
        if (mcast && mcast->ah) {
                struct dst_entry *dst = skb_dst(skb);
                struct neighbour *n = NULL;
+
+               rcu_read_lock();
                if (dst)
                        n = dst_get_neighbour(dst);
                if (n && !*to_ipoib_neigh(n)) {
@@ -734,7 +739,7 @@ out:
                                list_add_tail(&neigh->list, &mcast->neigh_list);
                        }
                }
-
+               rcu_read_unlock();
                spin_unlock_irqrestore(&priv->lock, flags);
                ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
                return;
index 09b93b11a274278b399e0adbfb1dc8e6917e35e9..e2a9867c19d52fce53cac578bdaf265d3211bba1 100644 (file)
@@ -1210,18 +1210,28 @@ static int elantech_reconnect(struct psmouse *psmouse)
  */
 static int elantech_set_properties(struct elantech_data *etd)
 {
+       /* This represents the version of IC body. */
        int ver = (etd->fw_version & 0x0f0000) >> 16;
 
+       /* Early version of Elan touchpads doesn't obey the rule. */
        if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
                etd->hw_version = 1;
-       else if (etd->fw_version < 0x150600)
-               etd->hw_version = 2;
-       else if (ver == 5)
-               etd->hw_version = 3;
-       else if (ver == 6)
-               etd->hw_version = 4;
-       else
-               return -1;
+       else {
+               switch (ver) {
+               case 2:
+               case 4:
+                       etd->hw_version = 2;
+                       break;
+               case 5:
+                       etd->hw_version = 3;
+                       break;
+               case 6:
+                       etd->hw_version = 4;
+                       break;
+               default:
+                       return -1;
+               }
+       }
 
        /*
         * Turn on packet checking by default.
index 4b2a42f9f0bb471748ee3d6676da48255fd73231..d4d08bd9205b87b7ddc617c55fee84ec6259a2b8 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/serio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <asm/mach-types.h>
 #include <plat/board-ams-delta.h>
index bb9f5d31f0d0616463609f4b20c940ee0ec2d451..b4cfc6c8be89db327134dd7dd722dfa2623d472a 100644 (file)
@@ -431,6 +431,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
                },
        },
+       {
+               /* Newer HP Pavilion dv4 models */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+               },
+       },
        { }
 };
 
@@ -560,6 +567,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
                },
        },
+       {
+               /* Newer HP Pavilion dv4 models */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+               },
+       },
        { }
 };
 
index 9c192e79f806836be3ef688821c897be30dd6142..288da5c1499d5432c14b2410136dfc05f82d18ff 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
index e8fdb8830f698184b08cb2a919b1358648ea4efb..46be456fcc00e01c10b2ae8106a83310b41d29b9 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
index 661b692573e7790e7d75a4b815cd7741dfe47c74..6d5628bb060115d6e3f032210f9bc862a0ef397b 100644 (file)
@@ -270,11 +270,8 @@ void led_blink_set(struct led_classdev *led_cdev,
        del_timer_sync(&led_cdev->blink_timer);
 
        if (led_cdev->blink_set &&
-           !led_cdev->blink_set(led_cdev, delay_on, delay_off)) {
-               led_cdev->blink_delay_on = *delay_on;
-               led_cdev->blink_delay_off = *delay_off;
+           !led_cdev->blink_set(led_cdev, delay_on, delay_off))
                return;
-       }
 
        /* blink with 1 Hz as default if nothing specified */
        if (!*delay_on && !*delay_off)
index 817f37a875c9be194c7b7c08736a98acde8d74cb..c9570fcf1cce10fdf06a607aba75d31331011668 100644 (file)
@@ -159,7 +159,7 @@ int macii_init(void)
        err = macii_init_via();
        if (err) goto out;
 
-       err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
+       err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
                          macii_interrupt);
        if (err) goto out;
 
index 9ab5b0c34f0d0e8ff5f759c1e59dfea3948e674a..34d02a91b29ff70ed3dea3b1ad667da46e2a366a 100644 (file)
@@ -122,8 +122,8 @@ maciisi_init(void)
                return err;
        }
 
-       if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST, 
-                       "ADB", maciisi_interrupt)) {
+       if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB",
+                       maciisi_interrupt)) {
                printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
                return -EAGAIN;
        }
index cb246667dd52b6f7f71595db6db1138c16ea3aa0..0a6806f80ab5cdf40d4dba56c41dc74ad3db772b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/vmalloc.h>
 #include <linux/version.h>
 #include <linux/shrinker.h>
+#include <linux/module.h>
 
 #define DM_MSG_PREFIX "bufio"
 
index 65fd85ec6514dabcb0d13720cb5f029b861e90a4..023fbc2d389ee086e2edf53168e969a24dba5cad 100644 (file)
@@ -8,7 +8,7 @@
 #include "dm-btree-internal.h"
 #include "dm-transaction-manager.h"
 
-#include <linux/module.h>
+#include <linux/export.h>
 
 /*
  * Removing an entry from a btree
index e0638be53ea4302460d9a47df1cbd7f736d145a7..bd1e7ffbe26c750a26a4b9341d925a98acf632b3 100644 (file)
@@ -8,7 +8,7 @@
 #include "dm-space-map.h"
 #include "dm-transaction-manager.h"
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/device-mapper.h>
 
 #define DM_MSG_PREFIX "btree"
index bb44a937fe635b1f38641ef771b3bd81ce8306d8..50ed53bf4aa2b1efe1136c2520067ece16bb9b35 100644 (file)
@@ -7,6 +7,7 @@
 #include "dm-space-map-checker.h"
 
 #include <linux/device-mapper.h>
+#include <linux/export.h>
 
 #ifdef CONFIG_DM_DEBUG_SPACE_MAPS
 
index aeff7852cf79bf731ab69370fffe9ce0f4c38537..fc469ba9f6277a7c701615a1b3d788a05fa52559 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/device-mapper.h>
 
 #define DM_MSG_PREFIX "space map disk"
index 728e89a3f97830c3290e282a5daa7788c4fc309c..6f8d38747d7f438294fca80e24a3e3a61441dda1 100644 (file)
@@ -10,7 +10,7 @@
 #include "dm-space-map-metadata.h"
 #include "dm-persistent-data-internal.h"
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/device-mapper.h>
 
index 472aedfb07cf35375ec5aa77421888cd6c64037d..297e260921787f490b63ddf88a9ea5adbdfd82c4 100644 (file)
@@ -3110,7 +3110,7 @@ static void handle_stripe(struct stripe_head *sh)
        struct r5dev *pdev, *qdev;
 
        clear_bit(STRIPE_HANDLE, &sh->state);
-       if (test_and_set_bit(STRIPE_ACTIVE, &sh->state)) {
+       if (test_and_set_bit_lock(STRIPE_ACTIVE, &sh->state)) {
                /* already being handled, ensure it gets handled
                 * again when current action finishes */
                set_bit(STRIPE_HANDLE, &sh->state);
@@ -3159,10 +3159,14 @@ static void handle_stripe(struct stripe_head *sh)
        /* check if the array has lost more than max_degraded devices and,
         * if so, some requests might need to be failed.
         */
-       if (s.failed > conf->max_degraded && s.to_read+s.to_write+s.written)
-               handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
-       if (s.failed > conf->max_degraded && s.syncing)
-               handle_failed_sync(conf, sh, &s);
+       if (s.failed > conf->max_degraded) {
+               sh->check_state = 0;
+               sh->reconstruct_state = 0;
+               if (s.to_read+s.to_write+s.written)
+                       handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
+               if (s.syncing)
+                       handle_failed_sync(conf, sh, &s);
+       }
 
        /*
         * might be able to return some write requests if the parity blocks
@@ -3371,7 +3375,7 @@ finish:
 
        return_io(s.return_bi);
 
-       clear_bit(STRIPE_ACTIVE, &sh->state);
+       clear_bit_unlock(STRIPE_ACTIVE, &sh->state);
 }
 
 static void raid5_activate_delayed(struct r5conf *conf)
index 2e8c288258a95153a97198f8f3d2708d5471d028..34434557ef65934d0652d926df3459d8bbc30c1c 100644 (file)
@@ -398,7 +398,6 @@ static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
        u8 i2c_r_data[24];
        u8 i = 0;
        u8 fifo_status = 0;
-       int ret;
        int status = 0;
 
        mxl_i2c("read %d bytes", count);
@@ -418,7 +417,7 @@ static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
                i2c_w_data[4+(i*3)] = 0x00;
        }
 
-       ret = mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
+       mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
 
        /* Check for I2C NACK status */
        if (mxl111sf_i2c_check_status(state) == 1) {
index 91dc1fc2825bf8ace4fa88bf33efe9b52ff6bd97..b741b3a7a325d423287512dce40440ad9556505a 100644 (file)
@@ -296,8 +296,7 @@ int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff)
                goto fail;
 
        ret = mxl111sf_write_reg(state, 0x00, 0x00);
-       if (mxl_fail(ret))
-               goto fail;
+       mxl_fail(ret);
 fail:
        return ret;
 }
@@ -328,11 +327,13 @@ int mxl111sf_idac_config(struct mxl111sf_state *state,
                /* set hysteresis value  reg: 0x0B<5:0> */
                ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG,
                                         (hysteresis_value & 0x3F));
+               mxl_fail(ret);
        }
 
        ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
+       mxl_fail(ret);
 
-       return val;
+       return ret;
 }
 
 /*
index 2446736b787115cb6e51f3e4fc32c2960a27694c..0df7f2a418140420c370e514e3c54a2da912820d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/media.h>
+#include <linux/module.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
index 725634d9736d5de28e1dd9f35719515abf6e5508..844a4d7797bc0be85ff01eae08837d5d49dbee69 100644 (file)
@@ -220,8 +220,8 @@ static int vidioc_querycap(struct file *file, void *priv,
        strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
        cap->bus_info[0] = 0;
        cap->version = KERNEL_VERSION(1, 0, 0);
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
-                                                   | V4L2_CAP_STREAMING;
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+                       V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
        return 0;
 }
 
index ecef127dbc66faf3a949360882a424d4c1c49182..1e8cdb77d4b8540a991bb55d98ef35225596c98f 100644 (file)
@@ -785,8 +785,8 @@ static int vidioc_querycap(struct file *file, void *priv,
        strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
        cap->bus_info[0] = 0;
        cap->version = KERNEL_VERSION(1, 0, 0);
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
-                         | V4L2_CAP_VIDEO_OUTPUT
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE
+                         | V4L2_CAP_VIDEO_OUTPUT_MPLANE
                          | V4L2_CAP_STREAMING;
        return 0;
 }
index 10c2364f3e8a56624babb71ac2f1d59f2c4c37f1..254d32688843bdc3f0a38a782e13fef2ec8d5a18 100644 (file)
@@ -1016,7 +1016,8 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
 
        menu_info = &mapping->menu_info[query_menu->index];
 
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+       if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+           (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
                s32 bitmap;
 
                if (!ctrl->cached) {
@@ -1225,7 +1226,8 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
                /* Valid menu indices are reported by the GET_RES request for
                 * UVC controls that support it.
                 */
-               if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+               if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+                   (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
                        if (!ctrl->cached) {
                                ret = uvc_ctrl_populate_cache(chain, ctrl);
                                if (ret < 0)
index f17f92b86a3093b3cedb1d3fd689a32977d37401..0f415dade05ae4bec936b2300f9c81e93fa535eb 100644 (file)
@@ -821,8 +821,8 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
        fill_event(&ev, ctrl, changes);
 
        list_for_each_entry(sev, &ctrl->ev_subs, node)
-               if (sev->fh && (sev->fh != fh ||
-                               (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
+               if (sev->fh != fh ||
+                   (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK))
                        v4l2_event_queue_fh(sev->fh, &ev);
 }
 
@@ -947,6 +947,7 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
                        if (ctrl->cluster[0]->has_volatiles)
                                ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
                }
+               fh = NULL;
        }
        if (changed || update_inactive) {
                /* If a control was changed that was not one of the controls
index 46037f225529d2e35a6eb0fb15c87368ac8dd54d..c26ad9637143bcc82bc0bb5618b207ccc07277ba 100644 (file)
@@ -216,6 +216,9 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
        unsigned long flags;
        unsigned i;
 
+       if (sub->type == V4L2_EVENT_ALL)
+               return -EINVAL;
+
        if (elems < 1)
                elems = 1;
        if (sub->type == V4L2_EVENT_CTRL) {
@@ -283,6 +286,7 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
 {
        struct v4l2_subscribed_event *sev;
        unsigned long flags;
+       int i;
 
        if (sub->type == V4L2_EVENT_ALL) {
                v4l2_event_unsubscribe_all(fh);
@@ -293,8 +297,12 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
 
        sev = v4l2_event_subscribed(fh, sub->type, sub->id);
        if (sev != NULL) {
+               /* Remove any pending events for this subscription */
+               for (i = 0; i < sev->in_use; i++) {
+                       list_del(&sev->events[sev_pos(sev, i)].list);
+                       fh->navailable--;
+               }
                list_del(&sev->list);
-               sev->fh = NULL;
        }
 
        spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
index 979e544388cbfbdea4efa2ea1c1bb321e1d37897..95a3f5e82aef14c74a81045baa26874eb008e7c1 100644 (file)
@@ -131,6 +131,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
                        continue;
 
                for (plane = 0; plane < vb->num_planes; ++plane) {
+                       vb->v4l2_planes[plane].length = q->plane_sizes[plane];
                        vb->v4l2_planes[plane].m.mem_offset = off;
 
                        dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n",
@@ -264,6 +265,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
        q->num_buffers -= buffers;
        if (!q->num_buffers)
                q->memory = 0;
+       INIT_LIST_HEAD(&q->queued_list);
 }
 
 /**
@@ -296,14 +298,14 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
 {
        unsigned int plane;
        for (plane = 0; plane < vb->num_planes; ++plane) {
+               void *mem_priv = vb->planes[plane].mem_priv;
                /*
                 * If num_users() has not been provided, call_memop
                 * will return 0, apparently nobody cares about this
                 * case anyway. If num_users() returns more than 1,
                 * we are not the only user of the plane's memory.
                 */
-               if (call_memop(q, plane, num_users,
-                               vb->planes[plane].mem_priv) > 1)
+               if (mem_priv && call_memop(q, plane, num_users, mem_priv) > 1)
                        return true;
        }
        return false;
index 4175544b491b51917c0c309194ba82de67327ec1..ec10629a0b0b151b5235432dc08bb238f4783b22 100644 (file)
@@ -13,6 +13,7 @@
  * TODO: Event handling with irq_chip. Waiting for PRCMU fw support.
  */
 
+#include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
index 6be1fe6b5f9ac70c8ef31df1a3d546a3dc695707..43c0ebb81956188b22f7ce2953eddc936f39ae3a 100644 (file)
@@ -4,6 +4,7 @@
  * Debugfs support for the AB5500 MFD driver
  */
 
+#include <linux/export.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/mfd/ab5500/ab5500.h>
index d593878d66d054e76f75860aec7176b9c012a5cf..5664696f2d3a8512c6ef96aca461dde22e5d486f 100644 (file)
@@ -472,7 +472,7 @@ config BMP085
          module will be called bmp085.
 
 config PCH_PHUB
-       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"
+       tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
        depends on PCI
        help
          This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
@@ -480,12 +480,13 @@ config PCH_PHUB
          processor. The Topcliff has MAC address and Option ROM data in SROM.
          This driver can access MAC address and Option ROM data in SROM.
 
-         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
-         Output Hub), ML7213 and ML7223.
-         ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
-         for MP(Media Phone) use.
-         ML7213/ML7223 is companion chip for Intel Atom E6xx series.
-         ML7213/ML7223 is completely compatible for Intel EG20T PCH.
+         This driver also can be used for LAPIS Semiconductor's IOH,
+         ML7213/ML7223/ML7831.
+         ML7213 which is for IVI(In-Vehicle Infotainment) use.
+         ML7223 IOH is for MP(Media Phone) use.
+         ML7831 IOH is for general purpose use.
+         ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
 
          To compile this driver as a module, choose M here: the module will
          be called pch_phub.
index a662f5987b6892591008291e3b5b05506918ed9e..82b2cb77ae197b2124ede9131dc4cbe0902ce0e8 100644 (file)
@@ -100,7 +100,7 @@ enum dpot_devid {
        AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27),
        AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
                        BRDAC0, 7, 28),
-       AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
+       AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
                        BRDAC0, 8, 29),
        AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
                        BRDAC0 | BRDAC1, 8, 30),
index 7ce6065dc20e806a06845f08bcec084adbb4418d..eb5cd28bc6d8d7a1917f7f15d82b267b692315f8 100644 (file)
@@ -945,8 +945,7 @@ static int fpga_of_remove(struct platform_device *op)
 /* CTL-CPLD Version Register */
 #define CTL_CPLD_VERSION       0x2000
 
-static int fpga_of_probe(struct platform_device *op,
-                        const struct of_device_id *match)
+static int fpga_of_probe(struct platform_device *op)
 {
        struct device_node *of_node = op->dev.of_node;
        struct device *this_device;
@@ -1107,7 +1106,7 @@ static struct of_device_id fpga_of_match[] = {
        {},
 };
 
-static struct of_platform_driver fpga_of_driver = {
+static struct platform_driver fpga_of_driver = {
        .probe          = fpga_of_probe,
        .remove         = fpga_of_remove,
        .driver         = {
@@ -1124,12 +1123,12 @@ static struct of_platform_driver fpga_of_driver = {
 static int __init fpga_init(void)
 {
        led_trigger_register_simple("fpga", &ledtrig_fpga);
-       return of_register_platform_driver(&fpga_of_driver);
+       return platform_driver_register(&fpga_of_driver);
 }
 
 static void __exit fpga_exit(void)
 {
-       of_unregister_platform_driver(&fpga_of_driver);
+       platform_driver_unregister(&fpga_of_driver);
        led_trigger_unregister_simple(ledtrig_fpga);
 }
 
index 3965821fef174c308ac73e37072d552287985d91..14e974b2a7812452d14ad2d92979e8d84483da7e 100644 (file)
@@ -1249,8 +1249,7 @@ static bool dma_filter(struct dma_chan *chan, void *data)
        return true;
 }
 
-static int data_of_probe(struct platform_device *op,
-                        const struct of_device_id *match)
+static int data_of_probe(struct platform_device *op)
 {
        struct device_node *of_node = op->dev.of_node;
        struct device *this_device;
@@ -1401,7 +1400,7 @@ static struct of_device_id data_of_match[] = {
        {},
 };
 
-static struct of_platform_driver data_of_driver = {
+static struct platform_driver data_of_driver = {
        .probe          = data_of_probe,
        .remove         = data_of_remove,
        .driver         = {
@@ -1417,12 +1416,12 @@ static struct of_platform_driver data_of_driver = {
 
 static int __init data_init(void)
 {
-       return of_register_platform_driver(&data_of_driver);
+       return platform_driver_register(&data_of_driver);
 }
 
 static void __exit data_exit(void)
 {
-       of_unregister_platform_driver(&data_of_driver);
+       platform_driver_unregister(&data_of_driver);
 }
 
 MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
index 26cf12ca7f503e5d2babb111ab6eaf132cf5c5a2..701edf6589705cb42f290a04c233239f7248760a 100644 (file)
@@ -85,7 +85,7 @@ config EEPROM_93XX46
 
 config EEPROM_DIGSY_MTC_CFG
        bool "DigsyMTC display configuration EEPROMs device"
-       depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO
+       depends on GPIO_MPC5200 && SPI_GPIO
        help
          This option enables access to display configuration EEPROMs
          on digsy_mtc board. You have to additionally select Microwire
index dee33addcaebf82c2652e089830fff7d442a8ed2..10fc4785dba7dd65330a7008db87a4423a0bedd5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset
                                              (Intel EG20T PCH)*/
 #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address
-                                               offset(OKI SEMICONDUCTOR ML7213)
+                                               offset(LAPIS Semicon ML7213)
                                              */
 #define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address
-                                               offset(OKI SEMICONDUCTOR ML7223)
+                                               offset(LAPIS Semicon ML7223)
                                              */
 
 /* MAX number of INT_REDUCE_CONTROL registers */
@@ -73,6 +73,9 @@
 #define PCI_DEVICE_ID_ROHM_ML7223_mPHUB        0x8012 /* for Bus-m */
 #define PCI_DEVICE_ID_ROHM_ML7223_nPHUB        0x8002 /* for Bus-n */
 
+/* Macros for ML7831 */
+#define PCI_DEVICE_ID_ROHM_ML7831_PHUB 0x8801
+
 /* SROM ACCESS Macro */
 #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
 
  * @pch_mac_start_address:             MAC address area start address
  * @pch_opt_rom_start_address:         Option ROM start address
  * @ioh_type:                          Save IOH type
+ * @pdev:                              pointer to pci device struct
  */
 struct pch_phub_reg {
        u32 phub_id_reg;
@@ -136,6 +140,7 @@ struct pch_phub_reg {
        u32 pch_mac_start_address;
        u32 pch_opt_rom_start_address;
        int ioh_type;
+       struct pci_dev *pdev;
 };
 
 /* SROM SPEC for MAC address assignment offset */
@@ -471,7 +476,7 @@ static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
        int retval;
        int i;
 
-       if (chip->ioh_type == 1) /* EG20T */
+       if ((chip->ioh_type == 1) || (chip->ioh_type == 5)) /* EG20T or ML7831*/
                retval = pch_phub_gbe_serial_rom_conf(chip);
        else    /* ML7223 */
                retval = pch_phub_gbe_serial_rom_conf_mp(chip);
@@ -498,6 +503,7 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
        unsigned int orom_size;
        int ret;
        int err;
+       ssize_t rom_size;
 
        struct pch_phub_reg *chip =
                dev_get_drvdata(container_of(kobj, struct device, kobj));
@@ -509,6 +515,10 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
        }
 
        /* Get Rom signature */
+       chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+       if (!chip->pch_phub_extrom_base_address)
+               goto exrom_map_err;
+
        pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address,
                                (unsigned char *)&rom_signature);
        rom_signature &= 0xff;
@@ -539,10 +549,13 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
                goto return_err;
        }
 return_ok:
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
        mutex_unlock(&pch_phub_mutex);
        return addr_offset;
 
 return_err:
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
+exrom_map_err:
        mutex_unlock(&pch_phub_mutex);
 return_err_nomutex:
        return err;
@@ -555,6 +568,7 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
        int err;
        unsigned int addr_offset;
        int ret;
+       ssize_t rom_size;
        struct pch_phub_reg *chip =
                dev_get_drvdata(container_of(kobj, struct device, kobj));
 
@@ -571,6 +585,12 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
                goto return_ok;
        }
 
+       chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+       if (!chip->pch_phub_extrom_base_address) {
+               err = -ENOMEM;
+               goto exrom_map_err;
+       }
+
        for (addr_offset = 0; addr_offset < count; addr_offset++) {
                if (PCH_PHUB_OROM_SIZE < off + addr_offset)
                        goto return_ok;
@@ -585,10 +605,14 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
        }
 
 return_ok:
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
        mutex_unlock(&pch_phub_mutex);
        return addr_offset;
 
 return_err:
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
+
+exrom_map_err:
        mutex_unlock(&pch_phub_mutex);
        return err;
 }
@@ -598,8 +622,14 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
 {
        u8 mac[8];
        struct pch_phub_reg *chip = dev_get_drvdata(dev);
+       ssize_t rom_size;
+
+       chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+       if (!chip->pch_phub_extrom_base_address)
+               return -ENOMEM;
 
        pch_phub_read_gbe_mac_addr(chip, mac);
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
 
        return sprintf(buf, "%pM\n", mac);
 }
@@ -608,6 +638,7 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t count)
 {
        u8 mac[6];
+       ssize_t rom_size;
        struct pch_phub_reg *chip = dev_get_drvdata(dev);
 
        if (count != 18)
@@ -617,7 +648,12 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
                (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
                (u32 *)&mac[4], (u32 *)&mac[5]);
 
+       chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+       if (!chip->pch_phub_extrom_base_address)
+               return -ENOMEM;
+
        pch_phub_write_gbe_mac_addr(chip, mac);
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
 
        return count;
 }
@@ -640,7 +676,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
        int retval;
 
        int ret;
-       ssize_t rom_size;
        struct pch_phub_reg *chip;
 
        chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
@@ -677,19 +712,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
                "in pch_phub_base_address variable is %p\n", __func__,
                chip->pch_phub_base_address);
 
-       if (id->driver_data != 3) {
-               chip->pch_phub_extrom_base_address =\
-                                                  pci_map_rom(pdev, &rom_size);
-               if (chip->pch_phub_extrom_base_address == 0) {
-                       dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__);
-                       ret = -ENOMEM;
-                       goto err_pci_map;
-               }
-               dev_dbg(&pdev->dev, "%s : "
-                       "pci_map_rom SUCCESS and value in "
-                       "pch_phub_extrom_base_address variable is %p\n",
-                       __func__, chip->pch_phub_extrom_base_address);
-       }
+       chip->pdev = pdev; /* Save pci device struct */
 
        if (id->driver_data == 1) { /* EG20T PCH */
                const char *board_name;
@@ -763,6 +786,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
                chip->pch_opt_rom_start_address =\
                                                 PCH_PHUB_ROM_START_ADDR_ML7223;
                chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
+       } else if (id->driver_data == 5) { /* ML7831 */
+               retval = sysfs_create_file(&pdev->dev.kobj,
+                                          &dev_attr_pch_mac.attr);
+               if (retval)
+                       goto err_sysfs_create;
+
+               retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+               if (retval)
+                       goto exit_bin_attr;
+
+               /* set the prefech value */
+               iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
+               /* set the interrupt delay value */
+               iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+               chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T;
+               chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T;
        }
 
        chip->ioh_type = id->driver_data;
@@ -773,8 +812,6 @@ exit_bin_attr:
        sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
 
 err_sysfs_create:
-       pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
-err_pci_map:
        pci_iounmap(pdev, chip->pch_phub_base_address);
 err_pci_iomap:
        pci_release_regions(pdev);
@@ -792,7 +829,6 @@ static void __devexit pch_phub_remove(struct pci_dev *pdev)
 
        sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
        sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-       pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
        pci_iounmap(pdev, chip->pch_phub_base_address);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
@@ -847,6 +883,7 @@ static struct pci_device_id pch_phub_pcidev_id[] = {
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2,  },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3,  },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4,  },
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7831_PHUB), 5,  },
        { }
 };
 MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id);
@@ -873,5 +910,5 @@ static void __exit pch_phub_pci_exit(void)
 module_init(pch_phub_pci_init);
 module_exit(pch_phub_pci_exit);
 
-MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB");
+MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB");
 MODULE_LICENSE("GPL");
index cfbddbef11de3b67c54be85797dd124843ca8596..43d073bc1d9c5fef61a1cb3a1e741a6cd6b6e0f9 100644 (file)
@@ -903,6 +903,6 @@ static void __exit spear_pcie_gadget_exit(void)
 }
 module_exit(spear_pcie_gadget_exit);
 
-MODULE_ALIAS("pcie-gadget-spear");
+MODULE_ALIAS("platform:pcie-gadget-spear");
 MODULE_AUTHOR("Pratyush Anand");
 MODULE_LICENSE("GPL");
index ae57769ba50d53c129bc1b6399b92db37c9bc010..4b976f00ea85137913a2b54e7dce63e590b809ac 100644 (file)
@@ -32,6 +32,7 @@
 /* VENDOR SPEC register */
 #define SDHCI_VENDOR_SPEC              0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK  0x00000002
+#define SDHCI_WTMK_LVL                 0x44
 #define SDHCI_MIX_CTRL                 0x48
 
 /*
@@ -476,6 +477,13 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
        if (is_imx53_esdhc(imx_data))
                imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
 
+       /*
+        * The imx6q ROM code will change the default watermark level setting
+        * to something insane.  Change it back here.
+        */
+       if (is_imx6q_usdhc(imx_data))
+               writel(0x08100810, host->ioaddr + SDHCI_WTMK_LVL);
+
        boarddata = &imx_data->boarddata;
        if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
                if (!host->mmc->parent->platform_data) {
index 66b616ebe536d512bf534d28ea48cf9db284d286..318a869286ab09581e761a391e57539faa7b5c77 100644 (file)
@@ -12,27 +12,17 @@ menuconfig MTD
 
 if MTD
 
-config MTD_DEBUG
-       bool "Debugging"
-       help
-         This turns on low-level debugging for the entire MTD sub-system.
-         Normally, you should say 'N'.
-
-config MTD_DEBUG_VERBOSE
-       int "Debugging verbosity (0 = quiet, 3 = noisy)"
-       depends on MTD_DEBUG
-       default "0"
-       help
-         Determines the verbosity level of the MTD debugging messages.
-
 config MTD_TESTS
-       tristate "MTD tests support"
+       tristate "MTD tests support (DANGEROUS)"
        depends on m
        help
          This option includes various MTD tests into compilation. The tests
          should normally be compiled as kernel modules. The modules perform
          various checks and verifications when loaded.
 
+         WARNING: some of the tests will ERASE entire MTD device which they
+         test. Do not use these tests unless you really know what you do.
+
 config MTD_REDBOOT_PARTS
        tristate "RedBoot partition table parsing"
        ---help---
@@ -137,7 +127,8 @@ config MTD_AFS_PARTS
          'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
 
 config MTD_OF_PARTS
-       def_bool y
+       tristate "OpenFirmware partitioning information support"
+       default Y
        depends on OF
        help
          This provides a partition parsing function which derives
index 39664c4229ff5139293dc63d27e09837d2a7696b..9aaac3ac89f3f55e64adb4d72f1e94c8c3967e16 100644 (file)
@@ -5,8 +5,8 @@
 # Core functionality.
 obj-$(CONFIG_MTD)              += mtd.o
 mtd-y                          := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o
-mtd-$(CONFIG_MTD_OF_PARTS)     += ofpart.o
 
+obj-$(CONFIG_MTD_OF_PARTS)     += ofpart.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)    += afs.o
index 302372c08b566cf61b7f0022aa059779bc123208..89a02f6f65dc1ae4c2752e6d941602c6a7295709 100644 (file)
@@ -162,8 +162,8 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
 }
 
 static int parse_afs_partitions(struct mtd_info *mtd,
-                         struct mtd_partition **pparts,
-                         unsigned long origin)
+                               struct mtd_partition **pparts,
+                               struct mtd_part_parser_data *data)
 {
        struct mtd_partition *parts;
        u_int mask, off, idx, sz;
index 95949b97de6a652814bcb25ba4e0c8a19ff05409..f40ea4547554d93def59fb55f1aac233fb12528f 100644 (file)
@@ -47,7 +47,7 @@ struct ar7_bin_rec {
 
 static int create_mtd_partitions(struct mtd_info *master,
                                 struct mtd_partition **pparts,
-                                unsigned long origin)
+                                struct mtd_part_parser_data *data)
 {
        struct ar7_bin_rec header;
        unsigned int offset;
index 23175edd5634ff16190b4d7be6ca74d3392e5e80..8d70895a58d6b424d34563e7f43a2a13df57ddfb 100644 (file)
@@ -145,8 +145,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
        if (((major << 8) | minor) < 0x3131) {
                /* CFI version 1.0 => don't trust bootloc */
 
-               DEBUG(MTD_DEBUG_LEVEL1,
-                       "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
+               pr_debug("%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
                        map->name, cfi->mfr, cfi->id);
 
                /* AFAICS all 29LV400 with a bottom boot block have a device ID
@@ -166,8 +165,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
                         * the 8-bit device ID.
                         */
                        (cfi->mfr == CFI_MFR_MACRONIX)) {
-                       DEBUG(MTD_DEBUG_LEVEL1,
-                               "%s: Macronix MX29LV400C with bottom boot block"
+                       pr_debug("%s: Macronix MX29LV400C with bottom boot block"
                                " detected\n", map->name);
                        extp->TopBottom = 2;    /* bottom boot */
                } else
@@ -178,8 +176,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
                        extp->TopBottom = 2;    /* bottom boot */
                }
 
-               DEBUG(MTD_DEBUG_LEVEL1,
-                       "%s: AMD CFI PRI V%c.%c has no boot block field;"
+               pr_debug("%s: AMD CFI PRI V%c.%c has no boot block field;"
                        " deduced %s from Device ID\n", map->name, major, minor,
                        extp->TopBottom == 2 ? "bottom" : "top");
        }
@@ -191,7 +188,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd)
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        if (cfi->cfiq->BufWriteTimeoutTyp) {
-               DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
+               pr_debug("Using buffer write method\n" );
                mtd->write = cfi_amdstd_write_buffers;
        }
 }
@@ -443,8 +440,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
        mtd->writesize = 1;
        mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n",
-               __func__, mtd->writebufsize);
+       pr_debug("MTD %s(): write buffer size %d\n", __func__,
+                       mtd->writebufsize);
 
        mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
 
@@ -1163,7 +1160,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
                return ret;
        }
 
-       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
+       pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
               __func__, adr, datum.x[0] );
 
        /*
@@ -1174,7 +1171,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
         */
        oldd = map_read(map, adr);
        if (map_word_equal(map, oldd, datum)) {
-               DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",
+               pr_debug("MTD %s(): NOP\n",
                       __func__);
                goto op_done;
        }
@@ -1400,7 +1397,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 
        datum = map_word_load(map, buf);
 
-       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
+       pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
               __func__, adr, datum.x[0] );
 
        XIP_INVAL_CACHED_RANGE(map, adr, len);
@@ -1587,7 +1584,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
                return ret;
        }
 
-       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+       pr_debug("MTD %s(): ERASE 0x%.8lx\n",
               __func__, chip->start );
 
        XIP_INVAL_CACHED_RANGE(map, adr, map->size);
@@ -1675,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
                return ret;
        }
 
-       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+       pr_debug("MTD %s(): ERASE 0x%.8lx\n",
               __func__, adr );
 
        XIP_INVAL_CACHED_RANGE(map, adr, len);
@@ -1801,8 +1798,7 @@ static int do_atmel_lock(struct map_info *map, struct flchip *chip,
                goto out_unlock;
        chip->state = FL_LOCKING;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
-             __func__, adr, len);
+       pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len);
 
        cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
                         cfi->device_type, NULL);
@@ -1837,8 +1833,7 @@ static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
                goto out_unlock;
        chip->state = FL_UNLOCKING;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
-             __func__, adr, len);
+       pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len);
 
        cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
                         cfi->device_type, NULL);
index 5e3cc80128aa90beec305b168b02c50f56f3b6f8..89c6595454a508925fe6c5accf0fbd44d1af56f9 100644 (file)
@@ -34,8 +34,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
 
        /* Refuse the operation if the we cannot look behind the chip */
        if (chip->start < 0x400000) {
-               DEBUG( MTD_DEBUG_LEVEL3,
-                       "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
+               pr_debug( "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
                        __func__, chip->start );
                return -EIO;
        }
index ea832ea0e4aacac6840dbfcfa73a9f7e0262667e..c443f527a53a5d9dae069701c9b1e0c497e63999 100644 (file)
@@ -1914,11 +1914,10 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi)
         * (oh and incidentaly the jedec spec - 3.5.3.3) the reset
         * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
         * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
-        * as they will ignore the writes and dont care what address
+        * as they will ignore the writes and don't care what address
         * the F0 is written to */
        if (cfi->addr_unlock1) {
-               DEBUG( MTD_DEBUG_LEVEL3,
-                      "reset unlock called %x %x \n",
+               pr_debug( "reset unlock called %x %x \n",
                       cfi->addr_unlock1,cfi->addr_unlock2);
                cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
                cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
@@ -1941,7 +1940,7 @@ static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int in
        uint8_t uaddr;
 
        if (!(jedec_table[index].devtypes & cfi->device_type)) {
-               DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n",
+               pr_debug("Rejecting potential %s with incompatible %d-bit device type\n",
                      jedec_table[index].name, 4 * (1<<cfi->device_type));
                return 0;
        }
@@ -2021,7 +2020,7 @@ static inline int jedec_match( uint32_t base,
                 * there aren't.
                 */
                if (finfo->dev_id > 0xff) {
-                       DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n",
+                       pr_debug("%s(): ID is not 8bit\n",
                               __func__);
                        goto match_done;
                }
@@ -2045,12 +2044,10 @@ static inline int jedec_match( uint32_t base,
        }
 
        /* the part size must fit in the memory window */
-       DEBUG( MTD_DEBUG_LEVEL3,
-              "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
+       pr_debug("MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
               __func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) );
        if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->size ) {
-               DEBUG( MTD_DEBUG_LEVEL3,
-                      "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
+               pr_debug("MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
                       __func__, finfo->mfr_id, finfo->dev_id,
                       1 << finfo->dev_size );
                goto match_done;
@@ -2061,13 +2058,12 @@ static inline int jedec_match( uint32_t base,
 
        uaddr = finfo->uaddr;
 
-       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
+       pr_debug("MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
               __func__, cfi->addr_unlock1, cfi->addr_unlock2 );
        if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
             && ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 ||
                  unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) {
-               DEBUG( MTD_DEBUG_LEVEL3,
-                       "MTD %s(): 0x%.4x 0x%.4x did not match\n",
+               pr_debug("MTD %s(): 0x%.4x 0x%.4x did not match\n",
                        __func__,
                        unlock_addrs[uaddr].addr1,
                        unlock_addrs[uaddr].addr2);
@@ -2083,15 +2079,13 @@ static inline int jedec_match( uint32_t base,
         * FIXME - write a driver that takes all of the chip info as
         * module parameters, doesn't probe but forces a load.
         */
-       DEBUG( MTD_DEBUG_LEVEL3,
-              "MTD %s(): check ID's disappear when not in ID mode\n",
+       pr_debug("MTD %s(): check ID's disappear when not in ID mode\n",
               __func__ );
        jedec_reset( base, map, cfi );
        mfr = jedec_read_mfr( map, base, cfi );
        id = jedec_read_id( map, base, cfi );
        if ( mfr == cfi->mfr && id == cfi->id ) {
-               DEBUG( MTD_DEBUG_LEVEL3,
-                      "MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
+               pr_debug("MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
                       "You might need to manually specify JEDEC parameters.\n",
                        __func__, cfi->mfr, cfi->id );
                goto match_done;
@@ -2104,7 +2098,7 @@ static inline int jedec_match( uint32_t base,
         * Put the device back in ID mode - only need to do this if we
         * were truly frobbing a real device.
         */
-       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
+       pr_debug("MTD %s(): return to ID mode\n", __func__ );
        if (cfi->addr_unlock1) {
                cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
                cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
@@ -2167,13 +2161,11 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
 
                cfi->mfr = jedec_read_mfr(map, base, cfi);
                cfi->id = jedec_read_id(map, base, cfi);
-               DEBUG(MTD_DEBUG_LEVEL3,
-                     "Search for id:(%02x %02x) interleave(%d) type(%d)\n",
+               pr_debug("Search for id:(%02x %02x) interleave(%d) type(%d)\n",
                        cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
                for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
                        if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
-                               DEBUG( MTD_DEBUG_LEVEL3,
-                                      "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
+                               pr_debug("MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
                                       __func__, cfi->mfr, cfi->id,
                                       cfi->addr_unlock1, cfi->addr_unlock2 );
                                if (!cfi_jedec_setup(map, cfi, i))
index 8cf667da24081a6826cf5772903a87ffbc56815b..ddf9ec6d9168ed3848fdd249a67c2c2053b43444 100644 (file)
@@ -189,10 +189,7 @@ static struct mtd_partition * newpart(char *s,
                             extra_mem_size;
                parts = kzalloc(alloc_size, GFP_KERNEL);
                if (!parts)
-               {
-                       printk(KERN_ERR ERRP "out of memory\n");
                        return NULL;
-               }
                extra_mem = (unsigned char *)(parts + *num_parts);
        }
        /* enter this partition (offset will be calculated later if it is zero at this point) */
@@ -317,8 +314,8 @@ static int mtdpart_setup_real(char *s)
  * the first one in the chain if a NULL mtd_id is passed in.
  */
 static int parse_cmdline_partitions(struct mtd_info *master,
-                             struct mtd_partition **pparts,
-                             unsigned long origin)
+                                   struct mtd_partition **pparts,
+                                   struct mtd_part_parser_data *data)
 {
        unsigned long offset;
        int i;
index 35081ce77fbdd0bd4260fd9a812ee6cae8dd08ca..283d887f78251168f40255fe80b788f6fba0b0fc 100644 (file)
@@ -249,6 +249,16 @@ config MTD_DOC2001PLUS
          under "NAND Flash Device Drivers" (currently that driver does not
          support all Millennium Plus devices).
 
+config MTD_DOCG3
+       tristate "M-Systems Disk-On-Chip G3"
+       ---help---
+         This provides an MTD device driver for the M-Systems DiskOnChip
+         G3 devices.
+
+         The driver provides access to G3 DiskOnChip, distributed by
+         M-Systems and now Sandisk. The support is very experimental,
+         and doesn't give access to any write operations.
+
 config MTD_DOCPROBE
        tristate
        select MTD_DOCECC
@@ -268,8 +278,7 @@ config MTD_DOCPROBE_ADVANCED
 config MTD_DOCPROBE_ADDRESS
        hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED
        depends on MTD_DOCPROBE
-       default "0x0000" if MTD_DOCPROBE_ADVANCED
-       default "0" if !MTD_DOCPROBE_ADVANCED
+       default "0x0"
        ---help---
          By default, the probe for DiskOnChip devices will look for a
          DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
index f3226b1d38fca15cbb9ace95a06e10dd9a6b2b8e..56c7cd462f11e33b191d73a6c3a7fe7d07e644b5 100644 (file)
@@ -5,6 +5,7 @@
 obj-$(CONFIG_MTD_DOC2000)      += doc2000.o
 obj-$(CONFIG_MTD_DOC2001)      += doc2001.o
 obj-$(CONFIG_MTD_DOC2001PLUS)  += doc2001plus.o
+obj-$(CONFIG_MTD_DOCG3)                += docg3.o
 obj-$(CONFIG_MTD_DOCPROBE)     += docprobe.o
 obj-$(CONFIG_MTD_DOCECC)       += docecc.o
 obj-$(CONFIG_MTD_SLRAM)                += slram.o
@@ -17,3 +18,5 @@ obj-$(CONFIG_MTD_BLOCK2MTD)   += block2mtd.o
 obj-$(CONFIG_MTD_DATAFLASH)    += mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)       += m25p80.o
 obj-$(CONFIG_MTD_SST25L)       += sst25l.o
+
+CFLAGS_docg3.o                 += -I$(src)
\ No newline at end of file
index f7fbf6025ef286de5f7fc61c1d3eada86695073f..e9fad915121924e636c32480b7b699bd6f76379f 100644 (file)
@@ -82,8 +82,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc)
        void __iomem *docptr = doc->virtadr;
        unsigned long timeo = jiffies + (HZ * 10);
 
-       DEBUG(MTD_DEBUG_LEVEL3,
-             "_DoC_WaitReady called for out-of-line wait\n");
+       pr_debug("_DoC_WaitReady called for out-of-line wait\n");
 
        /* Out-of-line routine to wait for chip response */
        while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
@@ -92,7 +91,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc)
                DoC_Delay(doc, 2);
 
                if (time_after(jiffies, timeo)) {
-                       DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+                       pr_debug("_DoC_WaitReady timed out.\n");
                        return -EIO;
                }
                udelay(1);
@@ -323,8 +322,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
 
        /* Reset the chip */
        if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
-               DEBUG(MTD_DEBUG_LEVEL2,
-                     "DoC_Command (reset) for %d,%d returned true\n",
+               pr_debug("DoC_Command (reset) for %d,%d returned true\n",
                      floor, chip);
                return 0;
        }
@@ -332,8 +330,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
 
        /* Read the NAND chip ID: 1. Send ReadID command */
        if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
-               DEBUG(MTD_DEBUG_LEVEL2,
-                     "DoC_Command (ReadID) for %d,%d returned true\n",
+               pr_debug("DoC_Command (ReadID) for %d,%d returned true\n",
                      floor, chip);
                return 0;
        }
@@ -699,7 +696,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
                        printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-                       /* Read the ECC syndrom through the DiskOnChip ECC
+                       /* Read the ECC syndrome through the DiskOnChip ECC
                           logic.  These syndrome will be all ZERO when there
                           is no error */
                        for (i = 0; i < 6; i++) {
@@ -930,7 +927,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
        uint8_t *buf = ops->oobbuf;
        size_t len = ops->len;
 
-       BUG_ON(ops->mode != MTD_OOB_PLACE);
+       BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
        ofs += ops->ooboffs;
 
@@ -1094,7 +1091,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
        struct DiskOnChip *this = mtd->priv;
        int ret;
 
-       BUG_ON(ops->mode != MTD_OOB_PLACE);
+       BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
        mutex_lock(&this->lock);
        ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
index 241192f05bc8d2cb8bcc601f2c61b06cd815274e..a3f7a27499be86a711b4c57018b8e8b958671969 100644 (file)
@@ -55,15 +55,14 @@ static int _DoC_WaitReady(void __iomem * docptr)
 {
        unsigned short c = 0xffff;
 
-       DEBUG(MTD_DEBUG_LEVEL3,
-             "_DoC_WaitReady called for out-of-line wait\n");
+       pr_debug("_DoC_WaitReady called for out-of-line wait\n");
 
        /* Out-of-line routine to wait for chip response */
        while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
                ;
 
        if (c == 0)
-               DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+               pr_debug("_DoC_WaitReady timed out.\n");
 
        return (c == 0);
 }
@@ -464,7 +463,7 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
                printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-               /* Read the ECC syndrom through the DiskOnChip ECC logic.
+               /* Read the ECC syndrome through the DiskOnChip ECC logic.
                   These syndrome will be all ZERO when there is no error */
                for (i = 0; i < 6; i++) {
                        syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
@@ -632,7 +631,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
        uint8_t *buf = ops->oobbuf;
        size_t len = ops->len;
 
-       BUG_ON(ops->mode != MTD_OOB_PLACE);
+       BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
        ofs += ops->ooboffs;
 
@@ -690,7 +689,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
        uint8_t *buf = ops->oobbuf;
        size_t len = ops->len;
 
-       BUG_ON(ops->mode != MTD_OOB_PLACE);
+       BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
        ofs += ops->ooboffs;
 
index 09ae0adc3ad07be984d9b936d9eda7fe24e0e86d..99351bc3e0ed32207ecf294ff03bad1b322ea74c 100644 (file)
@@ -61,15 +61,14 @@ static int _DoC_WaitReady(void __iomem * docptr)
 {
        unsigned int c = 0xffff;
 
-       DEBUG(MTD_DEBUG_LEVEL3,
-             "_DoC_WaitReady called for out-of-line wait\n");
+       pr_debug("_DoC_WaitReady called for out-of-line wait\n");
 
        /* Out-of-line routine to wait for chip response */
        while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
                ;
 
        if (c == 0)
-               DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+               pr_debug("_DoC_WaitReady timed out.\n");
 
        return (c == 0);
 }
@@ -655,7 +654,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
                printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-               /* Read the ECC syndrom through the DiskOnChip ECC logic.
+               /* Read the ECC syndrome through the DiskOnChip ECC logic.
                   These syndrome will be all ZERO when there is no error */
                for (i = 0; i < 6; i++)
                        syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
@@ -835,7 +834,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
        uint8_t *buf = ops->oobbuf;
        size_t len = ops->len;
 
-       BUG_ON(ops->mode != MTD_OOB_PLACE);
+       BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
        ofs += ops->ooboffs;
 
@@ -920,7 +919,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
        uint8_t *buf = ops->oobbuf;
        size_t len = ops->len;
 
-       BUG_ON(ops->mode != MTD_OOB_PLACE);
+       BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
        ofs += ops->ooboffs;
 
index 37ef29a73ee43993ded8414fb8dcbaafdbf1c20a..4a1c39b6f37df4276b2fb27749aadcd37995d235 100644 (file)
@@ -2,7 +2,7 @@
  * ECC algorithm for M-systems disk on chip. We use the excellent Reed
  * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the
  * GNU GPL License. The rest is simply to convert the disk on chip
- * syndrom into a standard syndom.
+ * syndrome into a standard syndome.
  *
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Copyright (C) 2000 Netgem S.A.
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
new file mode 100644 (file)
index 0000000..bdcf5df
--- /dev/null
@@ -0,0 +1,1114 @@
+/*
+ * Handles the M-Systems DiskOnChip G3 chip
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#define CREATE_TRACE_POINTS
+#include "docg3.h"
+
+/*
+ * This driver handles the DiskOnChip G3 flash memory.
+ *
+ * As no specification is available from M-Systems/Sandisk, this drivers lacks
+ * several functions available on the chip, as :
+ *  - block erase
+ *  - page write
+ *  - IPL write
+ *  - ECC fixing (lack of BCH algorith understanding)
+ *  - powerdown / powerup
+ *
+ * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and
+ * the driver assumes a 16bits data bus.
+ *
+ * DocG3 relies on 2 ECC algorithms, which are handled in hardware :
+ *  - a 1 byte Hamming code stored in the OOB for each page
+ *  - a 7 bytes BCH code stored in the OOB for each page
+ * The BCH part is only used for check purpose, no correction is available as
+ * some information is missing. What is known is that :
+ *  - BCH is in GF(2^14)
+ *  - BCH is over data of 520 bytes (512 page + 7 page_info bytes
+ *                                   + 1 hamming byte)
+ *  - BCH can correct up to 4 bits (t = 4)
+ *  - BCH syndroms are calculated in hardware, and checked in hardware as well
+ *
+ */
+
+static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
+{
+       u8 val = readb(docg3->base + reg);
+
+       trace_docg3_io(0, 8, reg, (int)val);
+       return val;
+}
+
+static inline u16 doc_readw(struct docg3 *docg3, u16 reg)
+{
+       u16 val = readw(docg3->base + reg);
+
+       trace_docg3_io(0, 16, reg, (int)val);
+       return val;
+}
+
+static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg)
+{
+       writeb(val, docg3->base + reg);
+       trace_docg3_io(1, 16, reg, val);
+}
+
+static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg)
+{
+       writew(val, docg3->base + reg);
+       trace_docg3_io(1, 16, reg, val);
+}
+
+static inline void doc_flash_command(struct docg3 *docg3, u8 cmd)
+{
+       doc_writeb(docg3, cmd, DOC_FLASHCOMMAND);
+}
+
+static inline void doc_flash_sequence(struct docg3 *docg3, u8 seq)
+{
+       doc_writeb(docg3, seq, DOC_FLASHSEQUENCE);
+}
+
+static inline void doc_flash_address(struct docg3 *docg3, u8 addr)
+{
+       doc_writeb(docg3, addr, DOC_FLASHADDRESS);
+}
+
+static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL };
+
+static int doc_register_readb(struct docg3 *docg3, int reg)
+{
+       u8 val;
+
+       doc_writew(docg3, reg, DOC_READADDRESS);
+       val = doc_readb(docg3, reg);
+       doc_vdbg("Read register %04x : %02x\n", reg, val);
+       return val;
+}
+
+static int doc_register_readw(struct docg3 *docg3, int reg)
+{
+       u16 val;
+
+       doc_writew(docg3, reg, DOC_READADDRESS);
+       val = doc_readw(docg3, reg);
+       doc_vdbg("Read register %04x : %04x\n", reg, val);
+       return val;
+}
+
+/**
+ * doc_delay - delay docg3 operations
+ * @docg3: the device
+ * @nbNOPs: the number of NOPs to issue
+ *
+ * As no specification is available, the right timings between chip commands are
+ * unknown. The only available piece of information are the observed nops on a
+ * working docg3 chip.
+ * Therefore, doc_delay relies on a busy loop of NOPs, instead of scheduler
+ * friendlier msleep() functions or blocking mdelay().
+ */
+static void doc_delay(struct docg3 *docg3, int nbNOPs)
+{
+       int i;
+
+       doc_dbg("NOP x %d\n", nbNOPs);
+       for (i = 0; i < nbNOPs; i++)
+               doc_writeb(docg3, 0, DOC_NOP);
+}
+
+static int is_prot_seq_error(struct docg3 *docg3)
+{
+       int ctrl;
+
+       ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+       return ctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR);
+}
+
+static int doc_is_ready(struct docg3 *docg3)
+{
+       int ctrl;
+
+       ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+       return ctrl & DOC_CTRL_FLASHREADY;
+}
+
+static int doc_wait_ready(struct docg3 *docg3)
+{
+       int maxWaitCycles = 100;
+
+       do {
+               doc_delay(docg3, 4);
+               cpu_relax();
+       } while (!doc_is_ready(docg3) && maxWaitCycles--);
+       doc_delay(docg3, 2);
+       if (maxWaitCycles > 0)
+               return 0;
+       else
+               return -EIO;
+}
+
+static int doc_reset_seq(struct docg3 *docg3)
+{
+       int ret;
+
+       doc_writeb(docg3, 0x10, DOC_FLASHCONTROL);
+       doc_flash_sequence(docg3, DOC_SEQ_RESET);
+       doc_flash_command(docg3, DOC_CMD_RESET);
+       doc_delay(docg3, 2);
+       ret = doc_wait_ready(docg3);
+
+       doc_dbg("doc_reset_seq() -> isReady=%s\n", ret ? "false" : "true");
+       return ret;
+}
+
+/**
+ * doc_read_data_area - Read data from data area
+ * @docg3: the device
+ * @buf: the buffer to fill in
+ * @len: the lenght to read
+ * @first: first time read, DOC_READADDRESS should be set
+ *
+ * Reads bytes from flash data. Handles the single byte / even bytes reads.
+ */
+static void doc_read_data_area(struct docg3 *docg3, void *buf, int len,
+                              int first)
+{
+       int i, cdr, len4;
+       u16 data16, *dst16;
+       u8 data8, *dst8;
+
+       doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len);
+       cdr = len & 0x3;
+       len4 = len - cdr;
+
+       if (first)
+               doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS);
+       dst16 = buf;
+       for (i = 0; i < len4; i += 2) {
+               data16 = doc_readw(docg3, DOC_IOSPACE_DATA);
+               *dst16 = data16;
+               dst16++;
+       }
+
+       if (cdr) {
+               doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE,
+                          DOC_READADDRESS);
+               doc_delay(docg3, 1);
+               dst8 = (u8 *)dst16;
+               for (i = 0; i < cdr; i++) {
+                       data8 = doc_readb(docg3, DOC_IOSPACE_DATA);
+                       *dst8 = data8;
+                       dst8++;
+               }
+       }
+}
+
+/**
+ * doc_set_data_mode - Sets the flash to reliable data mode
+ * @docg3: the device
+ *
+ * The reliable data mode is a bit slower than the fast mode, but less errors
+ * occur.  Entering the reliable mode cannot be done without entering the fast
+ * mode first.
+ */
+static void doc_set_reliable_mode(struct docg3 *docg3)
+{
+       doc_dbg("doc_set_reliable_mode()\n");
+       doc_flash_sequence(docg3, DOC_SEQ_SET_MODE);
+       doc_flash_command(docg3, DOC_CMD_FAST_MODE);
+       doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE);
+       doc_delay(docg3, 2);
+}
+
+/**
+ * doc_set_asic_mode - Set the ASIC mode
+ * @docg3: the device
+ * @mode: the mode
+ *
+ * The ASIC can work in 3 modes :
+ *  - RESET: all registers are zeroed
+ *  - NORMAL: receives and handles commands
+ *  - POWERDOWN: minimal poweruse, flash parts shut off
+ */
+static void doc_set_asic_mode(struct docg3 *docg3, u8 mode)
+{
+       int i;
+
+       for (i = 0; i < 12; i++)
+               doc_readb(docg3, DOC_IOSPACE_IPL);
+
+       mode |= DOC_ASICMODE_MDWREN;
+       doc_dbg("doc_set_asic_mode(%02x)\n", mode);
+       doc_writeb(docg3, mode, DOC_ASICMODE);
+       doc_writeb(docg3, ~mode, DOC_ASICMODECONFIRM);
+       doc_delay(docg3, 1);
+}
+
+/**
+ * doc_set_device_id - Sets the devices id for cascaded G3 chips
+ * @docg3: the device
+ * @id: the chip to select (amongst 0, 1, 2, 3)
+ *
+ * There can be 4 cascaded G3 chips. This function selects the one which will
+ * should be the active one.
+ */
+static void doc_set_device_id(struct docg3 *docg3, int id)
+{
+       u8 ctrl;
+
+       doc_dbg("doc_set_device_id(%d)\n", id);
+       doc_writeb(docg3, id, DOC_DEVICESELECT);
+       ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+
+       ctrl &= ~DOC_CTRL_VIOLATION;
+       ctrl |= DOC_CTRL_CE;
+       doc_writeb(docg3, ctrl, DOC_FLASHCONTROL);
+}
+
+/**
+ * doc_set_extra_page_mode - Change flash page layout
+ * @docg3: the device
+ *
+ * Normally, the flash page is split into the data (512 bytes) and the out of
+ * band data (16 bytes). For each, 4 more bytes can be accessed, where the wear
+ * leveling counters are stored.  To access this last area of 4 bytes, a special
+ * mode must be input to the flash ASIC.
+ *
+ * Returns 0 if no error occured, -EIO else.
+ */
+static int doc_set_extra_page_mode(struct docg3 *docg3)
+{
+       int fctrl;
+
+       doc_dbg("doc_set_extra_page_mode()\n");
+       doc_flash_sequence(docg3, DOC_SEQ_PAGE_SIZE_532);
+       doc_flash_command(docg3, DOC_CMD_PAGE_SIZE_532);
+       doc_delay(docg3, 2);
+
+       fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+       if (fctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR))
+               return -EIO;
+       else
+               return 0;
+}
+
+/**
+ * doc_seek - Set both flash planes to the specified block, page for reading
+ * @docg3: the device
+ * @block0: the first plane block index
+ * @block1: the second plane block index
+ * @page: the page index within the block
+ * @wear: if true, read will occur on the 4 extra bytes of the wear area
+ * @ofs: offset in page to read
+ *
+ * Programs the flash even and odd planes to the specific block and page.
+ * Alternatively, programs the flash to the wear area of the specified page.
+ */
+static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page,
+                        int wear, int ofs)
+{
+       int sector, ret = 0;
+
+       doc_dbg("doc_seek(blocks=(%d,%d), page=%d, ofs=%d, wear=%d)\n",
+               block0, block1, page, ofs, wear);
+
+       if (!wear && (ofs < 2 * DOC_LAYOUT_PAGE_SIZE)) {
+               doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1);
+               doc_flash_command(docg3, DOC_CMD_READ_PLANE1);
+               doc_delay(docg3, 2);
+       } else {
+               doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2);
+               doc_flash_command(docg3, DOC_CMD_READ_PLANE2);
+               doc_delay(docg3, 2);
+       }
+
+       doc_set_reliable_mode(docg3);
+       if (wear)
+               ret = doc_set_extra_page_mode(docg3);
+       if (ret)
+               goto out;
+
+       sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+       doc_flash_sequence(docg3, DOC_SEQ_READ);
+       doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+       doc_delay(docg3, 1);
+       doc_flash_address(docg3, sector & 0xff);
+       doc_flash_address(docg3, (sector >> 8) & 0xff);
+       doc_flash_address(docg3, (sector >> 16) & 0xff);
+       doc_delay(docg3, 1);
+
+       sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+       doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+       doc_delay(docg3, 1);
+       doc_flash_address(docg3, sector & 0xff);
+       doc_flash_address(docg3, (sector >> 8) & 0xff);
+       doc_flash_address(docg3, (sector >> 16) & 0xff);
+       doc_delay(docg3, 2);
+
+out:
+       return ret;
+}
+
+/**
+ * doc_read_page_ecc_init - Initialize hardware ECC engine
+ * @docg3: the device
+ * @len: the number of bytes covered by the ECC (BCH covered)
+ *
+ * The function does initialize the hardware ECC engine to compute the Hamming
+ * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes).
+ *
+ * Return 0 if succeeded, -EIO on error
+ */
+static int doc_read_page_ecc_init(struct docg3 *docg3, int len)
+{
+       doc_writew(docg3, DOC_ECCCONF0_READ_MODE
+                  | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE
+                  | (len & DOC_ECCCONF0_DATA_BYTES_MASK),
+                  DOC_ECCCONF0);
+       doc_delay(docg3, 4);
+       doc_register_readb(docg3, DOC_FLASHCONTROL);
+       return doc_wait_ready(docg3);
+}
+
+/**
+ * doc_read_page_prepare - Prepares reading data from a flash page
+ * @docg3: the device
+ * @block0: the first plane block index on flash memory
+ * @block1: the second plane block index on flash memory
+ * @page: the page index in the block
+ * @offset: the offset in the page (must be a multiple of 4)
+ *
+ * Prepares the page to be read in the flash memory :
+ *   - tell ASIC to map the flash pages
+ *   - tell ASIC to be in read mode
+ *
+ * After a call to this method, a call to doc_read_page_finish is mandatory,
+ * to end the read cycle of the flash.
+ *
+ * Read data from a flash page. The length to be read must be between 0 and
+ * (page_size + oob_size + wear_size), ie. 532, and a multiple of 4 (because
+ * the extra bytes reading is not implemented).
+ *
+ * As pages are grouped by 2 (in 2 planes), reading from a page must be done
+ * in two steps:
+ *  - one read of 512 bytes at offset 0
+ *  - one read of 512 bytes at offset 512 + 16
+ *
+ * Returns 0 if successful, -EIO if a read error occured.
+ */
+static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1,
+                                int page, int offset)
+{
+       int wear_area = 0, ret = 0;
+
+       doc_dbg("doc_read_page_prepare(blocks=(%d,%d), page=%d, ofsInPage=%d)\n",
+               block0, block1, page, offset);
+       if (offset >= DOC_LAYOUT_WEAR_OFFSET)
+               wear_area = 1;
+       if (!wear_area && offset > (DOC_LAYOUT_PAGE_OOB_SIZE * 2))
+               return -EINVAL;
+
+       doc_set_device_id(docg3, docg3->device_id);
+       ret = doc_reset_seq(docg3);
+       if (ret)
+               goto err;
+
+       /* Program the flash address block and page */
+       ret = doc_read_seek(docg3, block0, block1, page, wear_area, offset);
+       if (ret)
+               goto err;
+
+       doc_flash_command(docg3, DOC_CMD_READ_ALL_PLANES);
+       doc_delay(docg3, 2);
+       doc_wait_ready(docg3);
+
+       doc_flash_command(docg3, DOC_CMD_SET_ADDR_READ);
+       doc_delay(docg3, 1);
+       if (offset >= DOC_LAYOUT_PAGE_SIZE * 2)
+               offset -= 2 * DOC_LAYOUT_PAGE_SIZE;
+       doc_flash_address(docg3, offset >> 2);
+       doc_delay(docg3, 1);
+       doc_wait_ready(docg3);
+
+       doc_flash_command(docg3, DOC_CMD_READ_FLASH);
+
+       return 0;
+err:
+       doc_writeb(docg3, 0, DOC_DATAEND);
+       doc_delay(docg3, 2);
+       return -EIO;
+}
+
+/**
+ * doc_read_page_getbytes - Reads bytes from a prepared page
+ * @docg3: the device
+ * @len: the number of bytes to be read (must be a multiple of 4)
+ * @buf: the buffer to be filled in
+ * @first: 1 if first time read, DOC_READADDRESS should be set
+ *
+ */
+static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf,
+                                 int first)
+{
+       doc_read_data_area(docg3, buf, len, first);
+       doc_delay(docg3, 2);
+       return len;
+}
+
+/**
+ * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms
+ * @docg3: the device
+ * @syns:  the array of 7 integers where the syndroms will be stored
+ */
+static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns)
+{
+       int i;
+
+       for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
+               syns[i] = doc_register_readb(docg3, DOC_BCH_SYNDROM(i));
+}
+
+/**
+ * doc_read_page_finish - Ends reading of a flash page
+ * @docg3: the device
+ *
+ * As a side effect, resets the chip selector to 0. This ensures that after each
+ * read operation, the floor 0 is selected. Therefore, if the systems halts, the
+ * reboot will boot on floor 0, where the IPL is.
+ */
+static void doc_read_page_finish(struct docg3 *docg3)
+{
+       doc_writeb(docg3, 0, DOC_DATAEND);
+       doc_delay(docg3, 2);
+       doc_set_device_id(docg3, 0);
+}
+
+/**
+ * calc_block_sector - Calculate blocks, pages and ofs.
+
+ * @from: offset in flash
+ * @block0: first plane block index calculated
+ * @block1: second plane block index calculated
+ * @page: page calculated
+ * @ofs: offset in page
+ */
+static void calc_block_sector(loff_t from, int *block0, int *block1, int *page,
+                             int *ofs)
+{
+       uint sector;
+
+       sector = from / DOC_LAYOUT_PAGE_SIZE;
+       *block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES)
+               * DOC_LAYOUT_NBPLANES;
+       *block1 = *block0 + 1;
+       *page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES);
+       *page /= DOC_LAYOUT_NBPLANES;
+       if (sector % 2)
+               *ofs = DOC_LAYOUT_PAGE_OOB_SIZE;
+       else
+               *ofs = 0;
+}
+
+/**
+ * doc_read - Read bytes from flash
+ * @mtd: the device
+ * @from: the offset from first block and first page, in bytes, aligned on page
+ *        size
+ * @len: the number of bytes to read (must be a multiple of 4)
+ * @retlen: the number of bytes actually read
+ * @buf: the filled in buffer
+ *
+ * Reads flash memory pages. This function does not read the OOB chunk, but only
+ * the page data.
+ *
+ * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ */
+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
+            size_t *retlen, u_char *buf)
+{
+       struct docg3 *docg3 = mtd->priv;
+       int block0, block1, page, readlen, ret, ofs = 0;
+       int syn[DOC_ECC_BCH_SIZE], eccconf1;
+       u8 oob[DOC_LAYOUT_OOB_SIZE];
+
+       ret = -EINVAL;
+       doc_dbg("doc_read(from=%lld, len=%zu, buf=%p)\n", from, len, buf);
+       if (from % DOC_LAYOUT_PAGE_SIZE)
+               goto err;
+       if (len % 4)
+               goto err;
+       calc_block_sector(from, &block0, &block1, &page, &ofs);
+       if (block1 > docg3->max_block)
+               goto err;
+
+       *retlen = 0;
+       ret = 0;
+       readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+       while (!ret && len > 0) {
+               readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+               ret = doc_read_page_prepare(docg3, block0, block1, page, ofs);
+               if (ret < 0)
+                       goto err;
+               ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES);
+               if (ret < 0)
+                       goto err_in_read;
+               ret = doc_read_page_getbytes(docg3, readlen, buf, 1);
+               if (ret < readlen)
+                       goto err_in_read;
+               ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
+                                            oob, 0);
+               if (ret < DOC_LAYOUT_OOB_SIZE)
+                       goto err_in_read;
+
+               *retlen += readlen;
+               buf += readlen;
+               len -= readlen;
+
+               ofs ^= DOC_LAYOUT_PAGE_OOB_SIZE;
+               if (ofs == 0)
+                       page += 2;
+               if (page > DOC_ADDR_PAGE_MASK) {
+                       page = 0;
+                       block0 += 2;
+                       block1 += 2;
+               }
+
+               /*
+                * There should be a BCH bitstream fixing algorithm here ...
+                * By now, a page read failure is triggered by BCH error
+                */
+               doc_get_hw_bch_syndroms(docg3, syn);
+               eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1);
+
+               doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                        oob[0], oob[1], oob[2], oob[3], oob[4],
+                        oob[5], oob[6]);
+               doc_dbg("OOB - HAMMING: %02x\n", oob[7]);
+               doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                        oob[8], oob[9], oob[10], oob[11], oob[12],
+                        oob[13], oob[14]);
+               doc_dbg("OOB - UNUSED: %02x\n", oob[15]);
+               doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1);
+               doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]);
+
+               ret = -EBADMSG;
+               if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) {
+                       if (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR)
+                               goto err_in_read;
+                       if (is_prot_seq_error(docg3))
+                               goto err_in_read;
+               }
+               doc_read_page_finish(docg3);
+       }
+
+       return 0;
+err_in_read:
+       doc_read_page_finish(docg3);
+err:
+       return ret;
+}
+
+/**
+ * doc_read_oob - Read out of band bytes from flash
+ * @mtd: the device
+ * @from: the offset from first block and first page, in bytes, aligned on page
+ *        size
+ * @ops: the mtd oob structure
+ *
+ * Reads flash memory OOB area of pages.
+ *
+ * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ */
+static int doc_read_oob(struct mtd_info *mtd, loff_t from,
+                       struct mtd_oob_ops *ops)
+{
+       struct docg3 *docg3 = mtd->priv;
+       int block0, block1, page, ofs, ret;
+       u8 *buf = ops->oobbuf;
+       size_t len = ops->ooblen;
+
+       doc_dbg("doc_read_oob(from=%lld, buf=%p, len=%zu)\n", from, buf, len);
+       if (len != DOC_LAYOUT_OOB_SIZE)
+               return -EINVAL;
+
+       switch (ops->mode) {
+       case MTD_OPS_PLACE_OOB:
+               buf += ops->ooboffs;
+               break;
+       default:
+               break;
+       }
+
+       calc_block_sector(from, &block0, &block1, &page, &ofs);
+       if (block1 > docg3->max_block)
+               return -EINVAL;
+
+       ret = doc_read_page_prepare(docg3, block0, block1, page,
+                                   ofs + DOC_LAYOUT_PAGE_SIZE);
+       if (!ret)
+               ret = doc_read_page_ecc_init(docg3, DOC_LAYOUT_OOB_SIZE);
+       if (!ret)
+               ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
+                                            buf, 1);
+       doc_read_page_finish(docg3);
+
+       if (ret > 0)
+               ops->oobretlen = ret;
+       else
+               ops->oobretlen = 0;
+       return (ret > 0) ? 0 : ret;
+}
+
+static int doc_reload_bbt(struct docg3 *docg3)
+{
+       int block = DOC_LAYOUT_BLOCK_BBT;
+       int ret = 0, nbpages, page;
+       u_char *buf = docg3->bbt;
+
+       nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE);
+       for (page = 0; !ret && (page < nbpages); page++) {
+               ret = doc_read_page_prepare(docg3, block, block + 1,
+                                           page + DOC_LAYOUT_PAGE_BBT, 0);
+               if (!ret)
+                       ret = doc_read_page_ecc_init(docg3,
+                                                    DOC_LAYOUT_PAGE_SIZE);
+               if (!ret)
+                       doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE,
+                                              buf, 1);
+               buf += DOC_LAYOUT_PAGE_SIZE;
+       }
+       doc_read_page_finish(docg3);
+       return ret;
+}
+
+/**
+ * doc_block_isbad - Checks whether a block is good or not
+ * @mtd: the device
+ * @from: the offset to find the correct block
+ *
+ * Returns 1 if block is bad, 0 if block is good
+ */
+static int doc_block_isbad(struct mtd_info *mtd, loff_t from)
+{
+       struct docg3 *docg3 = mtd->priv;
+       int block0, block1, page, ofs, is_good;
+
+       calc_block_sector(from, &block0, &block1, &page, &ofs);
+       doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n",
+               from, block0, block1, page, ofs);
+
+       if (block0 < DOC_LAYOUT_BLOCK_FIRST_DATA)
+               return 0;
+       if (block1 > docg3->max_block)
+               return -EINVAL;
+
+       is_good = docg3->bbt[block0 >> 3] & (1 << (block0 & 0x7));
+       return !is_good;
+}
+
+/**
+ * doc_get_erase_count - Get block erase count
+ * @docg3: the device
+ * @from: the offset in which the block is.
+ *
+ * Get the number of times a block was erased. The number is the maximum of
+ * erase times between first and second plane (which should be equal normally).
+ *
+ * Returns The number of erases, or -EINVAL or -EIO on error.
+ */
+static int doc_get_erase_count(struct docg3 *docg3, loff_t from)
+{
+       u8 buf[DOC_LAYOUT_WEAR_SIZE];
+       int ret, plane1_erase_count, plane2_erase_count;
+       int block0, block1, page, ofs;
+
+       doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf);
+       if (from % DOC_LAYOUT_PAGE_SIZE)
+               return -EINVAL;
+       calc_block_sector(from, &block0, &block1, &page, &ofs);
+       if (block1 > docg3->max_block)
+               return -EINVAL;
+
+       ret = doc_reset_seq(docg3);
+       if (!ret)
+               ret = doc_read_page_prepare(docg3, block0, block1, page,
+                                           ofs + DOC_LAYOUT_WEAR_OFFSET);
+       if (!ret)
+               ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE,
+                                            buf, 1);
+       doc_read_page_finish(docg3);
+
+       if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK))
+               return -EIO;
+       plane1_erase_count = (u8)(~buf[1]) | ((u8)(~buf[4]) << 8)
+               | ((u8)(~buf[5]) << 16);
+       plane2_erase_count = (u8)(~buf[3]) | ((u8)(~buf[6]) << 8)
+               | ((u8)(~buf[7]) << 16);
+
+       return max(plane1_erase_count, plane2_erase_count);
+}
+
+/*
+ * Debug sysfs entries
+ */
+static int dbg_flashctrl_show(struct seq_file *s, void *p)
+{
+       struct docg3 *docg3 = (struct docg3 *)s->private;
+
+       int pos = 0;
+       u8 fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+
+       pos += seq_printf(s,
+                "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n",
+                fctrl,
+                fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-",
+                fctrl & DOC_CTRL_CE ? "active" : "inactive",
+                fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-",
+                fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-",
+                fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready");
+       return pos;
+}
+DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show);
+
+static int dbg_asicmode_show(struct seq_file *s, void *p)
+{
+       struct docg3 *docg3 = (struct docg3 *)s->private;
+
+       int pos = 0;
+       int pctrl = doc_register_readb(docg3, DOC_ASICMODE);
+       int mode = pctrl & 0x03;
+
+       pos += seq_printf(s,
+                        "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (",
+                        pctrl,
+                        pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0,
+                        pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0,
+                        pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0,
+                        pctrl & DOC_ASICMODE_MDWREN ? 1 : 0,
+                        pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0,
+                        mode >> 1, mode & 0x1);
+
+       switch (mode) {
+       case DOC_ASICMODE_RESET:
+               pos += seq_printf(s, "reset");
+               break;
+       case DOC_ASICMODE_NORMAL:
+               pos += seq_printf(s, "normal");
+               break;
+       case DOC_ASICMODE_POWERDOWN:
+               pos += seq_printf(s, "powerdown");
+               break;
+       }
+       pos += seq_printf(s, ")\n");
+       return pos;
+}
+DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show);
+
+static int dbg_device_id_show(struct seq_file *s, void *p)
+{
+       struct docg3 *docg3 = (struct docg3 *)s->private;
+       int pos = 0;
+       int id = doc_register_readb(docg3, DOC_DEVICESELECT);
+
+       pos += seq_printf(s, "DeviceId = %d\n", id);
+       return pos;
+}
+DEBUGFS_RO_ATTR(device_id, dbg_device_id_show);
+
+static int dbg_protection_show(struct seq_file *s, void *p)
+{
+       struct docg3 *docg3 = (struct docg3 *)s->private;
+       int pos = 0;
+       int protect = doc_register_readb(docg3, DOC_PROTECTION);
+       int dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
+       int dps0_low = doc_register_readb(docg3, DOC_DPS0_ADDRLOW);
+       int dps0_high = doc_register_readb(docg3, DOC_DPS0_ADDRHIGH);
+       int dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
+       int dps1_low = doc_register_readb(docg3, DOC_DPS1_ADDRLOW);
+       int dps1_high = doc_register_readb(docg3, DOC_DPS1_ADDRHIGH);
+
+       pos += seq_printf(s, "Protection = 0x%02x (",
+                        protect);
+       if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK)
+               pos += seq_printf(s, "FOUNDRY_OTP_LOCK,");
+       if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK)
+               pos += seq_printf(s, "CUSTOMER_OTP_LOCK,");
+       if (protect & DOC_PROTECT_LOCK_INPUT)
+               pos += seq_printf(s, "LOCK_INPUT,");
+       if (protect & DOC_PROTECT_STICKY_LOCK)
+               pos += seq_printf(s, "STICKY_LOCK,");
+       if (protect & DOC_PROTECT_PROTECTION_ENABLED)
+               pos += seq_printf(s, "PROTECTION ON,");
+       if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK)
+               pos += seq_printf(s, "IPL_DOWNLOAD_LOCK,");
+       if (protect & DOC_PROTECT_PROTECTION_ERROR)
+               pos += seq_printf(s, "PROTECT_ERR,");
+       else
+               pos += seq_printf(s, "NO_PROTECT_ERR");
+       pos += seq_printf(s, ")\n");
+
+       pos += seq_printf(s, "DPS0 = 0x%02x : "
+                        "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
+                        "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+                        dps0, dps0_low, dps0_high,
+                        !!(dps0 & DOC_DPS_OTP_PROTECTED),
+                        !!(dps0 & DOC_DPS_READ_PROTECTED),
+                        !!(dps0 & DOC_DPS_WRITE_PROTECTED),
+                        !!(dps0 & DOC_DPS_HW_LOCK_ENABLED),
+                        !!(dps0 & DOC_DPS_KEY_OK));
+       pos += seq_printf(s, "DPS1 = 0x%02x : "
+                        "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
+                        "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+                        dps1, dps1_low, dps1_high,
+                        !!(dps1 & DOC_DPS_OTP_PROTECTED),
+                        !!(dps1 & DOC_DPS_READ_PROTECTED),
+                        !!(dps1 & DOC_DPS_WRITE_PROTECTED),
+                        !!(dps1 & DOC_DPS_HW_LOCK_ENABLED),
+                        !!(dps1 & DOC_DPS_KEY_OK));
+       return pos;
+}
+DEBUGFS_RO_ATTR(protection, dbg_protection_show);
+
+static int __init doc_dbg_register(struct docg3 *docg3)
+{
+       struct dentry *root, *entry;
+
+       root = debugfs_create_dir("docg3", NULL);
+       if (!root)
+               return -ENOMEM;
+
+       entry = debugfs_create_file("flashcontrol", S_IRUSR, root, docg3,
+                                 &flashcontrol_fops);
+       if (entry)
+               entry = debugfs_create_file("asic_mode", S_IRUSR, root,
+                                           docg3, &asic_mode_fops);
+       if (entry)
+               entry = debugfs_create_file("device_id", S_IRUSR, root,
+                                           docg3, &device_id_fops);
+       if (entry)
+               entry = debugfs_create_file("protection", S_IRUSR, root,
+                                           docg3, &protection_fops);
+       if (entry) {
+               docg3->debugfs_root = root;
+               return 0;
+       } else {
+               debugfs_remove_recursive(root);
+               return -ENOMEM;
+       }
+}
+
+static void __exit doc_dbg_unregister(struct docg3 *docg3)
+{
+       debugfs_remove_recursive(docg3->debugfs_root);
+}
+
+/**
+ * doc_set_driver_info - Fill the mtd_info structure and docg3 structure
+ * @chip_id: The chip ID of the supported chip
+ * @mtd: The structure to fill
+ */
+static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
+{
+       struct docg3 *docg3 = mtd->priv;
+       int cfg;
+
+       cfg = doc_register_readb(docg3, DOC_CONFIGURATION);
+       docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0);
+
+       switch (chip_id) {
+       case DOC_CHIPID_G3:
+               mtd->name = "DiskOnChip G3";
+               docg3->max_block = 2047;
+               break;
+       }
+       mtd->type = MTD_NANDFLASH;
+       /*
+        * Once write methods are added, the correct flags will be set.
+        * mtd->flags = MTD_CAP_NANDFLASH;
+        */
+       mtd->flags = MTD_CAP_ROM;
+       mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE;
+       mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES;
+       mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
+       mtd->oobsize = DOC_LAYOUT_OOB_SIZE;
+       mtd->owner = THIS_MODULE;
+       mtd->erase = NULL;
+       mtd->point = NULL;
+       mtd->unpoint = NULL;
+       mtd->read = doc_read;
+       mtd->write = NULL;
+       mtd->read_oob = doc_read_oob;
+       mtd->write_oob = NULL;
+       mtd->sync = NULL;
+       mtd->block_isbad = doc_block_isbad;
+}
+
+/**
+ * doc_probe - Probe the IO space for a DiskOnChip G3 chip
+ * @pdev: platform device
+ *
+ * Probes for a G3 chip at the specified IO space in the platform data
+ * ressources.
+ *
+ * Returns 0 on success, -ENOMEM, -ENXIO on error
+ */
+static int __init docg3_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct docg3 *docg3;
+       struct mtd_info *mtd;
+       struct resource *ress;
+       int ret, bbt_nbpages;
+       u16 chip_id, chip_id_inv;
+
+       ret = -ENOMEM;
+       docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL);
+       if (!docg3)
+               goto nomem1;
+       mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
+       if (!mtd)
+               goto nomem2;
+       mtd->priv = docg3;
+
+       ret = -ENXIO;
+       ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!ress) {
+               dev_err(dev, "No I/O memory resource defined\n");
+               goto noress;
+       }
+       docg3->base = ioremap(ress->start, DOC_IOSPACE_SIZE);
+
+       docg3->dev = &pdev->dev;
+       docg3->device_id = 0;
+       doc_set_device_id(docg3, docg3->device_id);
+       doc_set_asic_mode(docg3, DOC_ASICMODE_RESET);
+       doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL);
+
+       chip_id = doc_register_readw(docg3, DOC_CHIPID);
+       chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV);
+
+       ret = -ENODEV;
+       if (chip_id != (u16)(~chip_id_inv)) {
+               doc_info("No device found at IO addr %p\n",
+                        (void *)ress->start);
+               goto nochipfound;
+       }
+
+       switch (chip_id) {
+       case DOC_CHIPID_G3:
+               doc_info("Found a G3 DiskOnChip at addr %p\n",
+                        (void *)ress->start);
+               break;
+       default:
+               doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id);
+               goto nochipfound;
+       }
+
+       doc_set_driver_info(chip_id, mtd);
+       platform_set_drvdata(pdev, mtd);
+
+       ret = -ENOMEM;
+       bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1,
+                                  8 * DOC_LAYOUT_PAGE_SIZE);
+       docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
+       if (!docg3->bbt)
+               goto nochipfound;
+       doc_reload_bbt(docg3);
+
+       ret = mtd_device_parse_register(mtd, part_probes,
+                                       NULL, NULL, 0);
+       if (ret)
+               goto register_error;
+
+       doc_dbg_register(docg3);
+       return 0;
+
+register_error:
+       kfree(docg3->bbt);
+nochipfound:
+       iounmap(docg3->base);
+noress:
+       kfree(mtd);
+nomem2:
+       kfree(docg3);
+nomem1:
+       return ret;
+}
+
+/**
+ * docg3_release - Release the driver
+ * @pdev: the platform device
+ *
+ * Returns 0
+ */
+static int __exit docg3_release(struct platform_device *pdev)
+{
+       struct mtd_info *mtd = platform_get_drvdata(pdev);
+       struct docg3 *docg3 = mtd->priv;
+
+       doc_dbg_unregister(docg3);
+       mtd_device_unregister(mtd);
+       iounmap(docg3->base);
+       kfree(docg3->bbt);
+       kfree(docg3);
+       kfree(mtd);
+       return 0;
+}
+
+static struct platform_driver g3_driver = {
+       .driver         = {
+               .name   = "docg3",
+               .owner  = THIS_MODULE,
+       },
+       .remove         = __exit_p(docg3_release),
+};
+
+static int __init docg3_init(void)
+{
+       return platform_driver_probe(&g3_driver, docg3_probe);
+}
+module_init(docg3_init);
+
+
+static void __exit docg3_exit(void)
+{
+       platform_driver_unregister(&g3_driver);
+}
+module_exit(docg3_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
+MODULE_DESCRIPTION("MTD driver for DiskOnChip G3");
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h
new file mode 100644 (file)
index 0000000..0d407be
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Handles the M-Systems DiskOnChip G3 chip
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _MTD_DOCG3_H
+#define _MTD_DOCG3_H
+
+/*
+ * Flash memory areas :
+ *   - 0x0000 .. 0x07ff : IPL
+ *   - 0x0800 .. 0x0fff : Data area
+ *   - 0x1000 .. 0x17ff : Registers
+ *   - 0x1800 .. 0x1fff : Unknown
+ */
+#define DOC_IOSPACE_IPL                        0x0000
+#define DOC_IOSPACE_DATA               0x0800
+#define DOC_IOSPACE_SIZE               0x2000
+
+/*
+ * DOC G3 layout and adressing scheme
+ *   A page address for the block "b", plane "P" and page "p":
+ *   address = [bbbb bPpp pppp]
+ */
+
+#define DOC_ADDR_PAGE_MASK             0x3f
+#define DOC_ADDR_BLOCK_SHIFT           6
+#define DOC_LAYOUT_NBPLANES            2
+#define DOC_LAYOUT_PAGES_PER_BLOCK     64
+#define DOC_LAYOUT_PAGE_SIZE           512
+#define DOC_LAYOUT_OOB_SIZE            16
+#define DOC_LAYOUT_WEAR_SIZE           8
+#define DOC_LAYOUT_PAGE_OOB_SIZE                               \
+       (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_SIZE)
+#define DOC_LAYOUT_WEAR_OFFSET         (DOC_LAYOUT_PAGE_OOB_SIZE * 2)
+#define DOC_LAYOUT_BLOCK_SIZE                                  \
+       (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE)
+#define DOC_ECC_BCH_SIZE               7
+#define DOC_ECC_BCH_COVERED_BYTES                              \
+       (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ +    \
+        DOC_LAYOUT_OOB_HAMMING_SZ + DOC_LAYOUT_OOB_BCH_SZ)
+
+/*
+ * Blocks distribution
+ */
+#define DOC_LAYOUT_BLOCK_BBT           0
+#define DOC_LAYOUT_BLOCK_OTP           0
+#define DOC_LAYOUT_BLOCK_FIRST_DATA    6
+
+#define DOC_LAYOUT_PAGE_BBT            4
+
+/*
+ * Extra page OOB (16 bytes wide) layout
+ */
+#define DOC_LAYOUT_OOB_PAGEINFO_OFS    0
+#define DOC_LAYOUT_OOB_HAMMING_OFS     7
+#define DOC_LAYOUT_OOB_BCH_OFS         8
+#define DOC_LAYOUT_OOB_UNUSED_OFS      15
+#define DOC_LAYOUT_OOB_PAGEINFO_SZ     7
+#define DOC_LAYOUT_OOB_HAMMING_SZ      1
+#define DOC_LAYOUT_OOB_BCH_SZ          7
+#define DOC_LAYOUT_OOB_UNUSED_SZ       1
+
+
+#define DOC_CHIPID_G3                  0x200
+#define DOC_ERASE_MARK                 0xaa
+/*
+ * Flash registers
+ */
+#define DOC_CHIPID                     0x1000
+#define DOC_TEST                       0x1004
+#define DOC_BUSLOCK                    0x1006
+#define DOC_ENDIANCONTROL              0x1008
+#define DOC_DEVICESELECT               0x100a
+#define DOC_ASICMODE                   0x100c
+#define DOC_CONFIGURATION              0x100e
+#define DOC_INTERRUPTCONTROL           0x1010
+#define DOC_READADDRESS                        0x101a
+#define DOC_DATAEND                    0x101e
+#define DOC_INTERRUPTSTATUS            0x1020
+
+#define DOC_FLASHSEQUENCE              0x1032
+#define DOC_FLASHCOMMAND               0x1034
+#define DOC_FLASHADDRESS               0x1036
+#define DOC_FLASHCONTROL               0x1038
+#define DOC_NOP                                0x103e
+
+#define DOC_ECCCONF0                   0x1040
+#define DOC_ECCCONF1                   0x1042
+#define DOC_ECCPRESET                  0x1044
+#define DOC_HAMMINGPARITY              0x1046
+#define DOC_BCH_SYNDROM(idx)           (0x1048 + (idx << 1))
+
+#define DOC_PROTECTION                 0x1056
+#define DOC_DPS0_ADDRLOW               0x1060
+#define DOC_DPS0_ADDRHIGH              0x1062
+#define DOC_DPS1_ADDRLOW               0x1064
+#define DOC_DPS1_ADDRHIGH              0x1066
+#define DOC_DPS0_STATUS                        0x106c
+#define DOC_DPS1_STATUS                        0x106e
+
+#define DOC_ASICMODECONFIRM            0x1072
+#define DOC_CHIPID_INV                 0x1074
+
+/*
+ * Flash sequences
+ * A sequence is preset before one or more commands are input to the chip.
+ */
+#define DOC_SEQ_RESET                  0x00
+#define DOC_SEQ_PAGE_SIZE_532          0x03
+#define DOC_SEQ_SET_MODE               0x09
+#define DOC_SEQ_READ                   0x12
+#define DOC_SEQ_SET_PLANE1             0x0e
+#define DOC_SEQ_SET_PLANE2             0x10
+#define DOC_SEQ_PAGE_SETUP             0x1d
+
+/*
+ * Flash commands
+ */
+#define DOC_CMD_READ_PLANE1            0x00
+#define DOC_CMD_SET_ADDR_READ          0x05
+#define DOC_CMD_READ_ALL_PLANES                0x30
+#define DOC_CMD_READ_PLANE2            0x50
+#define DOC_CMD_READ_FLASH             0xe0
+#define DOC_CMD_PAGE_SIZE_532          0x3c
+
+#define DOC_CMD_PROG_BLOCK_ADDR                0x60
+#define DOC_CMD_PROG_CYCLE1            0x80
+#define DOC_CMD_PROG_CYCLE2            0x10
+#define DOC_CMD_ERASECYCLE2            0xd0
+
+#define DOC_CMD_RELIABLE_MODE          0x22
+#define DOC_CMD_FAST_MODE              0xa2
+
+#define DOC_CMD_RESET                  0xff
+
+/*
+ * Flash register : DOC_FLASHCONTROL
+ */
+#define DOC_CTRL_VIOLATION             0x20
+#define DOC_CTRL_CE                    0x10
+#define DOC_CTRL_UNKNOWN_BITS          0x08
+#define DOC_CTRL_PROTECTION_ERROR      0x04
+#define DOC_CTRL_SEQUENCE_ERROR                0x02
+#define DOC_CTRL_FLASHREADY            0x01
+
+/*
+ * Flash register : DOC_ASICMODE
+ */
+#define DOC_ASICMODE_RESET             0x00
+#define DOC_ASICMODE_NORMAL            0x01
+#define DOC_ASICMODE_POWERDOWN         0x02
+#define DOC_ASICMODE_MDWREN            0x04
+#define DOC_ASICMODE_BDETCT_RESET      0x08
+#define DOC_ASICMODE_RSTIN_RESET       0x10
+#define DOC_ASICMODE_RAM_WE            0x20
+
+/*
+ * Flash register : DOC_ECCCONF0
+ */
+#define DOC_ECCCONF0_READ_MODE         0x8000
+#define DOC_ECCCONF0_AUTO_ECC_ENABLE   0x4000
+#define DOC_ECCCONF0_HAMMING_ENABLE    0x1000
+#define DOC_ECCCONF0_BCH_ENABLE                0x0800
+#define DOC_ECCCONF0_DATA_BYTES_MASK   0x07ff
+
+/*
+ * Flash register : DOC_ECCCONF1
+ */
+#define DOC_ECCCONF1_BCH_SYNDROM_ERR   0x80
+#define DOC_ECCCONF1_UNKOWN1           0x40
+#define DOC_ECCCONF1_UNKOWN2           0x20
+#define DOC_ECCCONF1_UNKOWN3           0x10
+#define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f
+
+/*
+ * Flash register : DOC_PROTECTION
+ */
+#define DOC_PROTECT_FOUNDRY_OTP_LOCK   0x01
+#define DOC_PROTECT_CUSTOMER_OTP_LOCK  0x02
+#define DOC_PROTECT_LOCK_INPUT         0x04
+#define DOC_PROTECT_STICKY_LOCK                0x08
+#define DOC_PROTECT_PROTECTION_ENABLED 0x10
+#define DOC_PROTECT_IPL_DOWNLOAD_LOCK  0x20
+#define DOC_PROTECT_PROTECTION_ERROR   0x80
+
+/*
+ * Flash register : DOC_DPS0_STATUS and DOC_DPS1_STATUS
+ */
+#define DOC_DPS_OTP_PROTECTED          0x01
+#define DOC_DPS_READ_PROTECTED         0x02
+#define DOC_DPS_WRITE_PROTECTED                0x04
+#define DOC_DPS_HW_LOCK_ENABLED                0x08
+#define DOC_DPS_KEY_OK                 0x80
+
+/*
+ * Flash register : DOC_CONFIGURATION
+ */
+#define DOC_CONF_IF_CFG                        0x80
+#define DOC_CONF_MAX_ID_MASK           0x30
+#define DOC_CONF_VCCQ_3V               0x01
+
+/*
+ * Flash register : DOC_READADDRESS
+ */
+#define DOC_READADDR_INC               0x8000
+#define DOC_READADDR_ONE_BYTE          0x4000
+#define DOC_READADDR_ADDR_MASK         0x1fff
+
+/**
+ * struct docg3 - DiskOnChip driver private data
+ * @dev: the device currently under control
+ * @base: mapped IO space
+ * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3)
+ * @if_cfg: if true, reads are on 16bits, else reads are on 8bits
+ * @bbt: bad block table cache
+ * @debugfs_root: debugfs root node
+ */
+struct docg3 {
+       struct device *dev;
+       void __iomem *base;
+       unsigned int device_id:4;
+       unsigned int if_cfg:1;
+       int max_block;
+       u8 *bbt;
+       struct dentry *debugfs_root;
+};
+
+#define doc_err(fmt, arg...) dev_err(docg3->dev, (fmt), ## arg)
+#define doc_info(fmt, arg...) dev_info(docg3->dev, (fmt), ## arg)
+#define doc_dbg(fmt, arg...) dev_dbg(docg3->dev, (fmt), ## arg)
+#define doc_vdbg(fmt, arg...) dev_vdbg(docg3->dev, (fmt), ## arg)
+
+#define DEBUGFS_RO_ATTR(name, show_fct) \
+       static int name##_open(struct inode *inode, struct file *file) \
+       { return single_open(file, show_fct, inode->i_private); }      \
+       static const struct file_operations name##_fops = { \
+               .owner = THIS_MODULE, \
+               .open = name##_open, \
+               .llseek = seq_lseek, \
+               .read = seq_read, \
+               .release = single_release \
+       };
+#endif
+
+/*
+ * Trace events part
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM docg3
+
+#if !defined(_MTD_DOCG3_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define _MTD_DOCG3_TRACE
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(docg3_io,
+           TP_PROTO(int op, int width, u16 reg, int val),
+           TP_ARGS(op, width, reg, val),
+           TP_STRUCT__entry(
+                   __field(int, op)
+                   __field(unsigned char, width)
+                   __field(u16, reg)
+                   __field(int, val)),
+           TP_fast_assign(
+                   __entry->op = op;
+                   __entry->width = width;
+                   __entry->reg = reg;
+                   __entry->val = val;),
+           TP_printk("docg3: %s%02d reg=%04x, val=%04x",
+                     __entry->op ? "write" : "read", __entry->width,
+                     __entry->reg, __entry->val)
+       );
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE docg3
+#include <trace/define_trace.h>
index d374603493a7da77c6f0004643809e0ac5862374..45116bb302972ba5cbde40719778aa4cb065635e 100644 (file)
 #include <linux/mtd/nand.h>
 #include <linux/mtd/doc2000.h>
 
-/* Where to look for the devices? */
-#ifndef CONFIG_MTD_DOCPROBE_ADDRESS
-#define CONFIG_MTD_DOCPROBE_ADDRESS 0
-#endif
-
 
 static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
 module_param(doc_config_location, ulong, 0);
index 772a0ff89e0f7e316279d82632d0893ad89b0f64..3a11ea628e58a2249bbe1d54939a77d2003690cb 100644 (file)
@@ -34,9 +34,6 @@
 /* debugging */
 //#define LART_DEBUG
 
-/* partition support */
-#define HAVE_PARTITIONS
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -44,9 +41,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
-#ifdef HAVE_PARTITIONS
 #include <linux/mtd/partitions.h>
-#endif
 
 #ifndef CONFIG_SA1100_LART
 #error This is for LART architecture only
@@ -598,7 +593,6 @@ static struct mtd_erase_region_info erase_regions[] = {
        }
 };
 
-#ifdef HAVE_PARTITIONS
 static struct mtd_partition lart_partitions[] = {
        /* blob */
        {
@@ -619,7 +613,7 @@ static struct mtd_partition lart_partitions[] = {
                .size   = INITRD_LEN,           /* MTDPART_SIZ_FULL */
        }
 };
-#endif
+#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
 
 static int __init lart_flash_init (void)
 {
@@ -668,7 +662,6 @@ static int __init lart_flash_init (void)
                           result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
                           result,mtd.eraseregions[result].numblocks);
 
-#ifdef HAVE_PARTITIONS
    printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
 
    for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
@@ -681,25 +674,16 @@ static int __init lart_flash_init (void)
                         result,lart_partitions[result].offset,
                         result,lart_partitions[result].size,lart_partitions[result].size / 1024);
 #endif
-#endif
 
-#ifndef HAVE_PARTITIONS
-   result = mtd_device_register(&mtd, NULL, 0);
-#else
    result = mtd_device_register(&mtd, lart_partitions,
                                 ARRAY_SIZE(lart_partitions));
-#endif
 
    return (result);
 }
 
 static void __exit lart_flash_exit (void)
 {
-#ifndef HAVE_PARTITIONS
-   mtd_device_unregister(&mtd);
-#else
    mtd_device_unregister(&mtd);
-#endif
 }
 
 module_init (lart_flash_init);
index 35180e475c4c565fded31dc91d6fe05c91aec805..884904d3f9d2deda9088046f8666e2f14b2aa664 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/of_platform.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
@@ -88,7 +89,6 @@ struct m25p {
        struct spi_device       *spi;
        struct mutex            lock;
        struct mtd_info         mtd;
-       unsigned                partitioned:1;
        u16                     page_size;
        u16                     addr_width;
        u8                      erase_opcode;
@@ -209,9 +209,8 @@ static int wait_till_ready(struct m25p *flash)
  */
 static int erase_chip(struct m25p *flash)
 {
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n",
-             dev_name(&flash->spi->dev), __func__,
-             (long long)(flash->mtd.size >> 10));
+       pr_debug("%s: %s %lldKiB\n", dev_name(&flash->spi->dev), __func__,
+                       (long long)(flash->mtd.size >> 10));
 
        /* Wait until finished previous write command. */
        if (wait_till_ready(flash))
@@ -250,9 +249,8 @@ static int m25p_cmdsz(struct m25p *flash)
  */
 static int erase_sector(struct m25p *flash, u32 offset)
 {
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
-                       dev_name(&flash->spi->dev), __func__,
-                       flash->mtd.erasesize / 1024, offset);
+       pr_debug("%s: %s %dKiB at 0x%08x\n", dev_name(&flash->spi->dev),
+                       __func__, flash->mtd.erasesize / 1024, offset);
 
        /* Wait until finished previous write command. */
        if (wait_till_ready(flash))
@@ -286,9 +284,9 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
        u32 addr,len;
        uint32_t rem;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n",
-             dev_name(&flash->spi->dev), __func__, "at",
-             (long long)instr->addr, (long long)instr->len);
+       pr_debug("%s: %s at 0x%llx, len %lld\n", dev_name(&flash->spi->dev),
+                       __func__, (long long)instr->addr,
+                       (long long)instr->len);
 
        /* sanity checks */
        if (instr->addr + instr->len > flash->mtd.size)
@@ -348,9 +346,8 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_transfer t[2];
        struct spi_message m;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-                       dev_name(&flash->spi->dev), __func__, "from",
-                       (u32)from, len);
+       pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+                       __func__, (u32)from, len);
 
        /* sanity checks */
        if (!len)
@@ -417,9 +414,8 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
        struct spi_transfer t[2];
        struct spi_message m;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-                       dev_name(&flash->spi->dev), __func__, "to",
-                       (u32)to, len);
+       pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+                       __func__, (u32)to, len);
 
        *retlen = 0;
 
@@ -510,9 +506,8 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
        size_t actual;
        int cmd_sz, ret;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-                       dev_name(&flash->spi->dev), __func__, "to",
-                       (u32)to, len);
+       pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+                       __func__, (u32)to, len);
 
        *retlen = 0;
 
@@ -661,6 +656,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
 
        { "at25df041a", INFO(0x1f4401, 0, 64 * 1024,   8, SECT_4K) },
+       { "at25df321a", INFO(0x1f4701, 0, 64 * 1024,  64, SECT_4K) },
        { "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
 
        { "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, SECT_4K) },
@@ -671,6 +667,7 @@ static const struct spi_device_id m25p_ids[] = {
        /* EON -- en25xxx */
        { "en25f32", INFO(0x1c3116, 0, 64 * 1024,  64, SECT_4K) },
        { "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
+       { "en25q32b", INFO(0x1c3016, 0, 64 * 1024,  64, 0) },
        { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
 
        /* Intel/Numonyx -- xxxs33b */
@@ -788,8 +785,8 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
         */
        tmp = spi_write_then_read(spi, &code, 1, id, 5);
        if (tmp < 0) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
-                       dev_name(&spi->dev), tmp);
+               pr_debug("%s: error %d reading JEDEC ID\n",
+                               dev_name(&spi->dev), tmp);
                return ERR_PTR(tmp);
        }
        jedec = id[0];
@@ -825,8 +822,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
        struct m25p                     *flash;
        struct flash_info               *info;
        unsigned                        i;
-       struct mtd_partition            *parts = NULL;
-       int                             nr_parts = 0;
+       struct mtd_part_parser_data     ppdata;
+
+#ifdef CONFIG_MTD_OF_PARTS
+       if (!of_device_is_available(spi->dev.of_node))
+               return -ENODEV;
+#endif
 
        /* Platform data helps sort out which chip type we have, as
         * well as how this board partitions it.  If we don't have
@@ -928,6 +929,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
        if (info->flags & M25P_NO_ERASE)
                flash->mtd.flags |= MTD_NO_ERASE;
 
+       ppdata.of_node = spi->dev.of_node;
        flash->mtd.dev.parent = &spi->dev;
        flash->page_size = info->page_size;
 
@@ -945,8 +947,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
        dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
                        (long long)flash->mtd.size >> 10);
 
-       DEBUG(MTD_DEBUG_LEVEL2,
-               "mtd .name = %s, .size = 0x%llx (%lldMiB) "
+       pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
                        ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
                flash->mtd.name,
                (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
@@ -955,8 +956,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 
        if (flash->mtd.numeraseregions)
                for (i = 0; i < flash->mtd.numeraseregions; i++)
-                       DEBUG(MTD_DEBUG_LEVEL2,
-                               "mtd.eraseregions[%d] = { .offset = 0x%llx, "
+                       pr_debug("mtd.eraseregions[%d] = { .offset = 0x%llx, "
                                ".erasesize = 0x%.8x (%uKiB), "
                                ".numblocks = %d }\n",
                                i, (long long)flash->mtd.eraseregions[i].offset,
@@ -968,41 +968,9 @@ static int __devinit m25p_probe(struct spi_device *spi)
        /* partitions should match sector boundaries; and it may be good to
         * use readonly partitions for writeprotected sectors (BP2..BP0).
         */
-       if (mtd_has_cmdlinepart()) {
-               static const char *part_probes[]
-                       = { "cmdlinepart", NULL, };
-
-               nr_parts = parse_mtd_partitions(&flash->mtd,
-                                               part_probes, &parts, 0);
-       }
-
-       if (nr_parts <= 0 && data && data->parts) {
-               parts = data->parts;
-               nr_parts = data->nr_parts;
-       }
-
-#ifdef CONFIG_MTD_OF_PARTS
-       if (nr_parts <= 0 && spi->dev.of_node) {
-               nr_parts = of_mtd_parse_partitions(&spi->dev,
-                                                  spi->dev.of_node, &parts);
-       }
-#endif
-
-       if (nr_parts > 0) {
-               for (i = 0; i < nr_parts; i++) {
-                       DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-                             "{.name = %s, .offset = 0x%llx, "
-                             ".size = 0x%llx (%lldKiB) }\n",
-                             i, parts[i].name,
-                             (long long)parts[i].offset,
-                             (long long)parts[i].size,
-                             (long long)(parts[i].size >> 10));
-               }
-               flash->partitioned = 1;
-       }
-
-       return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
-               -ENODEV : 0;
+       return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
+                       data ? data->parts : NULL,
+                       data ? data->nr_parts : 0);
 }
 
 
index 13749d458a313297fed127f39399b3432e3be1ff..d75c7af18a638d9f94588565e2d6b3271c95b05d 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/mutex.h>
 #include <linux/err.h>
 #include <linux/math64.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
@@ -24,7 +26,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
-
 /*
  * DataFlash is a kind of SPI flash.  Most AT45 chips have two buffers in
  * each chip, which may be used for double buffered I/O; but this driver
@@ -98,6 +99,16 @@ struct dataflash {
        struct mtd_info         mtd;
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id dataflash_dt_ids[] = {
+       { .compatible = "atmel,at45", },
+       { .compatible = "atmel,dataflash", },
+       { /* sentinel */ }
+};
+#else
+#define dataflash_dt_ids NULL
+#endif
+
 /* ......................................................................... */
 
 /*
@@ -122,7 +133,7 @@ static int dataflash_waitready(struct spi_device *spi)
        for (;;) {
                status = dataflash_status(spi);
                if (status < 0) {
-                       DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
+                       pr_debug("%s: status %d?\n",
                                        dev_name(&spi->dev), status);
                        status = 0;
                }
@@ -149,7 +160,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
        uint8_t                 *command;
        uint32_t                rem;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n",
+       pr_debug("%s: erase addr=0x%llx len 0x%llx\n",
              dev_name(&spi->dev), (long long)instr->addr,
              (long long)instr->len);
 
@@ -187,7 +198,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
                command[2] = (uint8_t)(pageaddr >> 8);
                command[3] = 0;
 
-               DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
+               pr_debug("ERASE %s: (%x) %x %x %x [%i]\n",
                        do_block ? "block" : "page",
                        command[0], command[1], command[2], command[3],
                        pageaddr);
@@ -238,8 +249,8 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
        uint8_t                 *command;
        int                     status;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
-               dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len));
+       pr_debug("%s: read 0x%x..0x%x\n", dev_name(&priv->spi->dev),
+                       (unsigned)from, (unsigned)(from + len));
 
        *retlen = 0;
 
@@ -255,7 +266,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        command = priv->command;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n",
+       pr_debug("READ: (%x) %x %x %x\n",
                command[0], command[1], command[2], command[3]);
 
        spi_message_init(&msg);
@@ -287,7 +298,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
                *retlen = msg.actual_length - 8;
                status = 0;
        } else
-               DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
+               pr_debug("%s: read %x..%x --> %d\n",
                        dev_name(&priv->spi->dev),
                        (unsigned)from, (unsigned)(from + len),
                        status);
@@ -314,7 +325,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
        int                     status = -EINVAL;
        uint8_t                 *command;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
+       pr_debug("%s: write 0x%x..0x%x\n",
                dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len));
 
        *retlen = 0;
@@ -340,7 +351,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
 
        mutex_lock(&priv->lock);
        while (remaining > 0) {
-               DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
+               pr_debug("write @ %i:%i len=%i\n",
                        pageaddr, offset, writelen);
 
                /* REVISIT:
@@ -368,12 +379,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
                        command[2] = (addr & 0x0000FF00) >> 8;
                        command[3] = 0;
 
-                       DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
+                       pr_debug("TRANSFER: (%x) %x %x %x\n",
                                command[0], command[1], command[2], command[3]);
 
                        status = spi_sync(spi, &msg);
                        if (status < 0)
-                               DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
+                               pr_debug("%s: xfer %u -> %d\n",
                                        dev_name(&spi->dev), addr, status);
 
                        (void) dataflash_waitready(priv->spi);
@@ -386,7 +397,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
                command[2] = (addr & 0x0000FF00) >> 8;
                command[3] = (addr & 0x000000FF);
 
-               DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n",
+               pr_debug("PROGRAM: (%x) %x %x %x\n",
                        command[0], command[1], command[2], command[3]);
 
                x[1].tx_buf = writebuf;
@@ -395,7 +406,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
                status = spi_sync(spi, &msg);
                spi_transfer_del(x + 1);
                if (status < 0)
-                       DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
+                       pr_debug("%s: pgm %u/%u -> %d\n",
                                dev_name(&spi->dev), addr, writelen, status);
 
                (void) dataflash_waitready(priv->spi);
@@ -410,12 +421,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
                command[2] = (addr & 0x0000FF00) >> 8;
                command[3] = 0;
 
-               DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n",
+               pr_debug("COMPARE: (%x) %x %x %x\n",
                        command[0], command[1], command[2], command[3]);
 
                status = spi_sync(spi, &msg);
                if (status < 0)
-                       DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
+                       pr_debug("%s: compare %u -> %d\n",
                                dev_name(&spi->dev), addr, status);
 
                status = dataflash_waitready(priv->spi);
@@ -634,11 +645,10 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 {
        struct dataflash                *priv;
        struct mtd_info                 *device;
+       struct mtd_part_parser_data     ppdata;
        struct flash_platform_data      *pdata = spi->dev.platform_data;
        char                            *otp_tag = "";
        int                             err = 0;
-       struct mtd_partition            *parts;
-       int                             nr_parts = 0;
 
        priv = kzalloc(sizeof *priv, GFP_KERNEL);
        if (!priv)
@@ -677,28 +687,11 @@ add_dataflash_otp(struct spi_device *spi, char *name,
                        pagesize, otp_tag);
        dev_set_drvdata(&spi->dev, priv);
 
-       if (mtd_has_cmdlinepart()) {
-               static const char *part_probes[] = { "cmdlinepart", NULL, };
-
-               nr_parts = parse_mtd_partitions(device, part_probes, &parts,
-                                               0);
-       }
+       ppdata.of_node = spi->dev.of_node;
+       err = mtd_device_parse_register(device, NULL, &ppdata,
+                       pdata ? pdata->parts : NULL,
+                       pdata ? pdata->nr_parts : 0);
 
-       if (nr_parts <= 0 && pdata && pdata->parts) {
-               parts = pdata->parts;
-               nr_parts = pdata->nr_parts;
-       }
-
-       if (nr_parts > 0) {
-               priv->partitioned = 1;
-               err = mtd_device_register(device, parts, nr_parts);
-               goto out;
-       }
-
-       if (mtd_device_register(device, NULL, 0) == 1)
-               err = -ENODEV;
-
-out:
        if (!err)
                return 0;
 
@@ -787,7 +780,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
         */
        tmp = spi_write_then_read(spi, &code, 1, id, 3);
        if (tmp < 0) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
+               pr_debug("%s: error %d reading JEDEC ID\n",
                        dev_name(&spi->dev), tmp);
                return ERR_PTR(tmp);
        }
@@ -804,7 +797,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
                        tmp < ARRAY_SIZE(dataflash_data);
                        tmp++, info++) {
                if (info->jedec_id == jedec) {
-                       DEBUG(MTD_DEBUG_LEVEL1, "%s: OTP, sector protect%s\n",
+                       pr_debug("%s: OTP, sector protect%s\n",
                                dev_name(&spi->dev),
                                (info->flags & SUP_POW2PS)
                                        ? ", binary pagesize" : ""
@@ -812,8 +805,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
                        if (info->flags & SUP_POW2PS) {
                                status = dataflash_status(spi);
                                if (status < 0) {
-                                       DEBUG(MTD_DEBUG_LEVEL1,
-                                               "%s: status error %d\n",
+                                       pr_debug("%s: status error %d\n",
                                                dev_name(&spi->dev), status);
                                        return ERR_PTR(status);
                                }
@@ -878,7 +870,7 @@ static int __devinit dataflash_probe(struct spi_device *spi)
         */
        status = dataflash_status(spi);
        if (status <= 0 || status == 0xff) {
-               DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
+               pr_debug("%s: status error %d\n",
                                dev_name(&spi->dev), status);
                if (status == 0 || status == 0xff)
                        status = -ENODEV;
@@ -914,14 +906,14 @@ static int __devinit dataflash_probe(struct spi_device *spi)
                break;
        /* obsolete AT45DB1282 not (yet?) supported */
        default:
-               DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
-                               dev_name(&spi->dev), status & 0x3c);
+               pr_debug("%s: unsupported device (%x)\n", dev_name(&spi->dev),
+                               status & 0x3c);
                status = -ENODEV;
        }
 
        if (status < 0)
-               DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
-                               dev_name(&spi->dev), status);
+               pr_debug("%s: add_dataflash --> %d\n", dev_name(&spi->dev),
+                               status);
 
        return status;
 }
@@ -931,7 +923,7 @@ static int __devexit dataflash_remove(struct spi_device *spi)
        struct dataflash        *flash = dev_get_drvdata(&spi->dev);
        int                     status;
 
-       DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev));
+       pr_debug("%s: remove\n", dev_name(&spi->dev));
 
        status = mtd_device_unregister(&flash->mtd);
        if (status == 0) {
@@ -946,6 +938,7 @@ static struct spi_driver dataflash_driver = {
                .name           = "mtd_dataflash",
                .bus            = &spi_bus_type,
                .owner          = THIS_MODULE,
+               .of_match_table = dataflash_dt_ids,
        },
 
        .probe          = dataflash_probe,
index 83e80c65d6e70ce9b508591ff814eab6150c9d08..d38ef3bffe8d0723806835df2d1093a017757380 100644 (file)
@@ -52,8 +52,6 @@ struct sst25l_flash {
        struct spi_device       *spi;
        struct mutex            lock;
        struct mtd_info         mtd;
-
-       int                     partitioned;
 };
 
 struct flash_info {
@@ -381,8 +379,6 @@ static int __devinit sst25l_probe(struct spi_device *spi)
        struct sst25l_flash *flash;
        struct flash_platform_data *data;
        int ret, i;
-       struct mtd_partition *parts = NULL;
-       int nr_parts = 0;
 
        flash_info = sst25l_match_device(spi);
        if (!flash_info)
@@ -414,8 +410,7 @@ static int __devinit sst25l_probe(struct spi_device *spi)
        dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name,
                 (long long)flash->mtd.size >> 10);
 
-       DEBUG(MTD_DEBUG_LEVEL2,
-             "mtd .name = %s, .size = 0x%llx (%lldMiB) "
+       pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
              ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
              flash->mtd.name,
              (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
@@ -423,37 +418,10 @@ static int __devinit sst25l_probe(struct spi_device *spi)
              flash->mtd.numeraseregions);
 
 
-       if (mtd_has_cmdlinepart()) {
-               static const char *part_probes[] = {"cmdlinepart", NULL};
-
-               nr_parts = parse_mtd_partitions(&flash->mtd,
-                                               part_probes,
-                                               &parts, 0);
-       }
-
-       if (nr_parts <= 0 && data && data->parts) {
-               parts = data->parts;
-               nr_parts = data->nr_parts;
-       }
-
-       if (nr_parts > 0) {
-               for (i = 0; i < nr_parts; i++) {
-                       DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-                             "{.name = %s, .offset = 0x%llx, "
-                             ".size = 0x%llx (%lldKiB) }\n",
-                             i, parts[i].name,
-                             (long long)parts[i].offset,
-                             (long long)parts[i].size,
-                             (long long)(parts[i].size >> 10));
-               }
-
-               flash->partitioned = 1;
-               return mtd_device_register(&flash->mtd, parts,
-                                          nr_parts);
-       }
-
-       ret = mtd_device_register(&flash->mtd, NULL, 0);
-       if (ret == 1) {
+       ret = mtd_device_parse_register(&flash->mtd, NULL, 0,
+                       data ? data->parts : NULL,
+                       data ? data->nr_parts : 0);
+       if (ret) {
                kfree(flash);
                dev_set_drvdata(&spi->dev, NULL);
                return -ENODEV;
index 037b399df3f1a384dbdc45b9c6d9dbf0d3c8abaf..c7382bb686c679efef42dd5218cce645002512eb 100644 (file)
@@ -339,7 +339,7 @@ static int erase_xfer(partition_t *part,
     struct erase_info *erase;
 
     xfer = &part->XferInfo[xfernum];
-    DEBUG(1, "ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
+    pr_debug("ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
     xfer->state = XFER_ERASING;
 
     /* Is there a free erase slot? Always in MTD. */
@@ -415,7 +415,7 @@ static int prepare_xfer(partition_t *part, int i)
     xfer = &part->XferInfo[i];
     xfer->state = XFER_FAILED;
 
-    DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
+    pr_debug("ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
 
     /* Write the transfer unit header */
     header = part->header;
@@ -476,7 +476,7 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
 
     eun = &part->EUNInfo[srcunit];
     xfer = &part->XferInfo[xferunit];
-    DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",
+    pr_debug("ftl_cs: copying block 0x%x to 0x%x\n",
          eun->Offset, xfer->Offset);
 
 
@@ -598,7 +598,7 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
     unit with the fewest erases, and usually pick the data unit with
     the most deleted blocks.  But with a small probability, pick the
     oldest data unit instead.  This means that we generally postpone
-    the next reclaimation as long as possible, but shuffle static
+    the next reclamation as long as possible, but shuffle static
     stuff around a bit for wear leveling.
 
 ======================================================================*/
@@ -609,8 +609,8 @@ static int reclaim_block(partition_t *part)
     uint32_t best;
     int queued, ret;
 
-    DEBUG(0, "ftl_cs: reclaiming space...\n");
-    DEBUG(3, "NumTransferUnits == %x\n", part->header.NumTransferUnits);
+    pr_debug("ftl_cs: reclaiming space...\n");
+    pr_debug("NumTransferUnits == %x\n", part->header.NumTransferUnits);
     /* Pick the least erased transfer unit */
     best = 0xffffffff; xfer = 0xffff;
     do {
@@ -618,22 +618,22 @@ static int reclaim_block(partition_t *part)
        for (i = 0; i < part->header.NumTransferUnits; i++) {
            int n=0;
            if (part->XferInfo[i].state == XFER_UNKNOWN) {
-               DEBUG(3,"XferInfo[%d].state == XFER_UNKNOWN\n",i);
+               pr_debug("XferInfo[%d].state == XFER_UNKNOWN\n",i);
                n=1;
                erase_xfer(part, i);
            }
            if (part->XferInfo[i].state == XFER_ERASING) {
-               DEBUG(3,"XferInfo[%d].state == XFER_ERASING\n",i);
+               pr_debug("XferInfo[%d].state == XFER_ERASING\n",i);
                n=1;
                queued = 1;
            }
            else if (part->XferInfo[i].state == XFER_ERASED) {
-               DEBUG(3,"XferInfo[%d].state == XFER_ERASED\n",i);
+               pr_debug("XferInfo[%d].state == XFER_ERASED\n",i);
                n=1;
                prepare_xfer(part, i);
            }
            if (part->XferInfo[i].state == XFER_PREPARED) {
-               DEBUG(3,"XferInfo[%d].state == XFER_PREPARED\n",i);
+               pr_debug("XferInfo[%d].state == XFER_PREPARED\n",i);
                n=1;
                if (part->XferInfo[i].EraseCount <= best) {
                    best = part->XferInfo[i].EraseCount;
@@ -641,12 +641,12 @@ static int reclaim_block(partition_t *part)
                }
            }
                if (!n)
-                   DEBUG(3,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
+                   pr_debug("XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
 
        }
        if (xfer == 0xffff) {
            if (queued) {
-               DEBUG(1, "ftl_cs: waiting for transfer "
+               pr_debug("ftl_cs: waiting for transfer "
                      "unit to be prepared...\n");
                if (part->mbd.mtd->sync)
                        part->mbd.mtd->sync(part->mbd.mtd);
@@ -656,7 +656,7 @@ static int reclaim_block(partition_t *part)
                    printk(KERN_NOTICE "ftl_cs: reclaim failed: no "
                           "suitable transfer units!\n");
                else
-                   DEBUG(1, "ftl_cs: reclaim failed: no "
+                   pr_debug("ftl_cs: reclaim failed: no "
                          "suitable transfer units!\n");
 
                return -EIO;
@@ -666,7 +666,7 @@ static int reclaim_block(partition_t *part)
 
     eun = 0;
     if ((jiffies % shuffle_freq) == 0) {
-       DEBUG(1, "ftl_cs: recycling freshest block...\n");
+       pr_debug("ftl_cs: recycling freshest block...\n");
        best = 0xffffffff;
        for (i = 0; i < part->DataUnits; i++)
            if (part->EUNInfo[i].EraseCount <= best) {
@@ -686,7 +686,7 @@ static int reclaim_block(partition_t *part)
                printk(KERN_NOTICE "ftl_cs: reclaim failed: "
                       "no free blocks!\n");
            else
-               DEBUG(1,"ftl_cs: reclaim failed: "
+               pr_debug("ftl_cs: reclaim failed: "
                       "no free blocks!\n");
 
            return -EIO;
@@ -771,7 +771,7 @@ static uint32_t find_free(partition_t *part)
        printk(KERN_NOTICE "ftl_cs: bad free list!\n");
        return 0;
     }
-    DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun);
+    pr_debug("ftl_cs: found free block at %d in %d\n", blk, eun);
     return blk;
 
 } /* find_free */
@@ -791,7 +791,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
     int ret;
     size_t offset, retlen;
 
-    DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
+    pr_debug("ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
          part, sector, nblocks);
     if (!(part->state & FTL_FORMATTED)) {
        printk(KERN_NOTICE "ftl_cs: bad partition\n");
@@ -840,7 +840,7 @@ static int set_bam_entry(partition_t *part, uint32_t log_addr,
     int ret;
     size_t retlen, offset;
 
-    DEBUG(2, "ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
+    pr_debug("ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
          part, log_addr, virt_addr);
     bsize = 1 << part->header.EraseUnitSize;
     eun = log_addr / bsize;
@@ -905,7 +905,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
     int ret;
     size_t retlen, offset;
 
-    DEBUG(2, "ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
+    pr_debug("ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
          part, sector, nblocks);
     if (!(part->state & FTL_FORMATTED)) {
        printk(KERN_NOTICE "ftl_cs: bad partition\n");
@@ -1011,7 +1011,7 @@ static int ftl_discardsect(struct mtd_blktrans_dev *dev,
        partition_t *part = (void *)dev;
        uint32_t bsize = 1 << part->header.EraseUnitSize;
 
-       DEBUG(1, "FTL erase sector %ld for %d sectors\n",
+       pr_debug("FTL erase sector %ld for %d sectors\n",
              sector, nr_sects);
 
        while (nr_sects) {
index d7592e67d04861cfc2a952112445ef0601dd58ce..dd034efd18751c8aaded3779f8ba85df06110bc5 100644 (file)
@@ -63,14 +63,12 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
                return;
        }
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
+       pr_debug("INFTL: add_mtd for %s\n", mtd->name);
 
        inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
 
-       if (!inftl) {
-               printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
+       if (!inftl)
                return;
-       }
 
        inftl->mbd.mtd = mtd;
        inftl->mbd.devnum = -1;
@@ -133,7 +131,7 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
 {
        struct INFTLrecord *inftl = (void *)dev;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: remove_dev (i=%d)\n", dev->devnum);
+       pr_debug("INFTL: remove_dev (i=%d)\n", dev->devnum);
 
        del_mtd_blktrans_dev(dev);
 
@@ -154,7 +152,7 @@ int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
        struct mtd_oob_ops ops;
        int res;
 
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = offs & (mtd->writesize - 1);
        ops.ooblen = len;
        ops.oobbuf = buf;
@@ -174,7 +172,7 @@ int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
        struct mtd_oob_ops ops;
        int res;
 
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = offs & (mtd->writesize - 1);
        ops.ooblen = len;
        ops.oobbuf = buf;
@@ -194,7 +192,7 @@ static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
        struct mtd_oob_ops ops;
        int res;
 
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = offs;
        ops.ooblen = mtd->oobsize;
        ops.oobbuf = oob;
@@ -215,16 +213,16 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate)
        u16 pot = inftl->LastFreeEUN;
        int silly = inftl->nb_blocks;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=%p,"
-               "desperate=%d)\n", inftl, desperate);
+       pr_debug("INFTL: INFTL_findfreeblock(inftl=%p,desperate=%d)\n",
+                       inftl, desperate);
 
        /*
         * Normally, we force a fold to happen before we run out of free
         * blocks completely.
         */
        if (!desperate && inftl->numfreeEUNs < 2) {
-               DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free "
-                       "EUNs (%d)\n", inftl->numfreeEUNs);
+               pr_debug("INFTL: there are too few free EUNs (%d)\n",
+                               inftl->numfreeEUNs);
                return BLOCK_NIL;
        }
 
@@ -259,8 +257,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
        struct inftl_oob oob;
        size_t retlen;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
-               "pending=%d)\n", inftl, thisVUC, pendingblock);
+       pr_debug("INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,pending=%d)\n",
+                       inftl, thisVUC, pendingblock);
 
        memset(BlockMap, 0xff, sizeof(BlockMap));
        memset(BlockDeleted, 0, sizeof(BlockDeleted));
@@ -323,8 +321,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
         * Chain, and the Erase Unit into which we are supposed to be copying.
         * Go for it.
         */
-       DEBUG(MTD_DEBUG_LEVEL1, "INFTL: folding chain %d into unit %d\n",
-               thisVUC, targetEUN);
+       pr_debug("INFTL: folding chain %d into unit %d\n", thisVUC, targetEUN);
 
        for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) {
                unsigned char movebuf[SECTORSIZE];
@@ -349,14 +346,13 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
                ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) +
                                (block * SECTORSIZE), SECTORSIZE, &retlen,
                                movebuf);
-               if (ret < 0 && ret != -EUCLEAN) {
+               if (ret < 0 && !mtd_is_bitflip(ret)) {
                        ret = mtd->read(mtd,
                                        (inftl->EraseSize * BlockMap[block]) +
                                        (block * SECTORSIZE), SECTORSIZE,
                                        &retlen, movebuf);
                        if (ret != -EIO)
-                               DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
-                                     "away on retry?\n");
+                               pr_debug("INFTL: error went away on retry?\n");
                }
                memset(&oob, 0xff, sizeof(struct inftl_oob));
                oob.b.Status = oob.b.Status1 = SECTOR_USED;
@@ -372,8 +368,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
         * is important, by doing oldest first if we crash/reboot then it
         * it is relatively simple to clean up the mess).
         */
-       DEBUG(MTD_DEBUG_LEVEL1, "INFTL: want to erase virtual chain %d\n",
-               thisVUC);
+       pr_debug("INFTL: want to erase virtual chain %d\n", thisVUC);
 
        for (;;) {
                /* Find oldest unit in chain. */
@@ -421,7 +416,7 @@ static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
        u16 ChainLength = 0, thislen;
        u16 chain, EUN;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=%p,"
+       pr_debug("INFTL: INFTL_makefreeblock(inftl=%p,"
                "pending=%d)\n", inftl, pendingblock);
 
        for (chain = 0; chain < inftl->nb_blocks; chain++) {
@@ -484,8 +479,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
        size_t retlen;
        int silly, silly2 = 3;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=%p,"
-               "block=%d)\n", inftl, block);
+       pr_debug("INFTL: INFTL_findwriteunit(inftl=%p,block=%d)\n",
+                       inftl, block);
 
        do {
                /*
@@ -501,8 +496,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
                                       blockofs, 8, &retlen, (char *)&bci);
 
                        status = bci.Status | bci.Status1;
-                       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
-                               "EUN %d is %x\n", block , writeEUN, status);
+                       pr_debug("INFTL: status of block %d in EUN %d is %x\n",
+                                       block , writeEUN, status);
 
                        switch(status) {
                        case SECTOR_FREE:
@@ -555,9 +550,9 @@ hitused:
                         * Hopefully we free something, lets try again.
                         * This time we are desperate...
                         */
-                       DEBUG(MTD_DEBUG_LEVEL1, "INFTL: using desperate==1 "
-                               "to find free EUN to accommodate write to "
-                               "VUC %d\n", thisVUC);
+                       pr_debug("INFTL: using desperate==1 to find free EUN "
+                                       "to accommodate write to VUC %d\n",
+                                       thisVUC);
                        writeEUN = INFTL_findfreeblock(inftl, 1);
                        if (writeEUN == BLOCK_NIL) {
                                /*
@@ -647,7 +642,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
        struct inftl_bci bci;
        size_t retlen;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=%p,"
+       pr_debug("INFTL: INFTL_trydeletechain(inftl=%p,"
                "thisVUC=%d)\n", inftl, thisVUC);
 
        memset(BlockUsed, 0, sizeof(BlockUsed));
@@ -711,7 +706,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
         * For each block in the chain free it and make it available
         * for future use. Erase from the oldest unit first.
         */
-       DEBUG(MTD_DEBUG_LEVEL1, "INFTL: deleting empty VUC %d\n", thisVUC);
+       pr_debug("INFTL: deleting empty VUC %d\n", thisVUC);
 
        for (;;) {
                u16 *prevEUN = &inftl->VUtable[thisVUC];
@@ -719,7 +714,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
 
                /* If the chain is all gone already, we're done */
                if (thisEUN == BLOCK_NIL) {
-                       DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN);
+                       pr_debug("INFTL: Empty VUC %d for deletion was already absent\n", thisEUN);
                        return;
                }
 
@@ -731,7 +726,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
                        thisEUN = *prevEUN;
                }
 
-               DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n",
+               pr_debug("Deleting EUN %d from VUC %d\n",
                      thisEUN, thisVUC);
 
                if (INFTL_formatblock(inftl, thisEUN) < 0) {
@@ -767,7 +762,7 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
        size_t retlen;
        struct inftl_bci bci;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=%p,"
+       pr_debug("INFTL: INFTL_deleteblock(inftl=%p,"
                "block=%d)\n", inftl, block);
 
        while (thisEUN < inftl->nb_blocks) {
@@ -826,7 +821,7 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
        struct inftl_oob oob;
        char *p, *pend;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=%p,block=%ld,"
+       pr_debug("INFTL: inftl_writeblock(inftl=%p,block=%ld,"
                "buffer=%p)\n", inftl, block, buffer);
 
        /* Is block all zero? */
@@ -876,7 +871,7 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
        struct inftl_bci bci;
        size_t retlen;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
+       pr_debug("INFTL: inftl_readblock(inftl=%p,block=%ld,"
                "buffer=%p)\n", inftl, block, buffer);
 
        while (thisEUN < inftl->nb_blocks) {
@@ -922,7 +917,7 @@ foundit:
                int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer);
 
                /* Handle corrected bit flips gracefully */
-               if (ret < 0 && ret != -EUCLEAN)
+               if (ret < 0 && !mtd_is_bitflip(ret))
                        return -EIO;
        }
        return 0;
index 104052e774b06a33ce56191f62077d29b8af57e6..2ff601f816cebd12b4210b199e85fbcbdfb424cf 100644 (file)
@@ -53,7 +53,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
        struct INFTLPartition *ip;
        size_t retlen;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl);
+       pr_debug("INFTL: find_boot_record(inftl=%p)\n", inftl);
 
         /*
         * Assume logical EraseSize == physical erasesize for starting the
@@ -139,24 +139,20 @@ static int find_boot_record(struct INFTLrecord *inftl)
                mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
                mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
 
-#ifdef CONFIG_MTD_DEBUG_VERBOSE
-               if (CONFIG_MTD_DEBUG_VERBOSE >= 2) {
-                       printk("INFTL: Media Header ->\n"
-                               "    bootRecordID          = %s\n"
-                               "    NoOfBootImageBlocks   = %d\n"
-                               "    NoOfBinaryPartitions  = %d\n"
-                               "    NoOfBDTLPartitions    = %d\n"
-                               "    BlockMultiplerBits    = %d\n"
-                               "    FormatFlgs            = %d\n"
-                               "    OsakVersion           = 0x%x\n"
-                               "    PercentUsed           = %d\n",
-                               mh->bootRecordID, mh->NoOfBootImageBlocks,
-                               mh->NoOfBinaryPartitions,
-                               mh->NoOfBDTLPartitions,
-                               mh->BlockMultiplierBits, mh->FormatFlags,
-                               mh->OsakVersion, mh->PercentUsed);
-               }
-#endif
+               pr_debug("INFTL: Media Header ->\n"
+                        "    bootRecordID          = %s\n"
+                        "    NoOfBootImageBlocks   = %d\n"
+                        "    NoOfBinaryPartitions  = %d\n"
+                        "    NoOfBDTLPartitions    = %d\n"
+                        "    BlockMultiplerBits    = %d\n"
+                        "    FormatFlgs            = %d\n"
+                        "    OsakVersion           = 0x%x\n"
+                        "    PercentUsed           = %d\n",
+                        mh->bootRecordID, mh->NoOfBootImageBlocks,
+                        mh->NoOfBinaryPartitions,
+                        mh->NoOfBDTLPartitions,
+                        mh->BlockMultiplierBits, mh->FormatFlags,
+                        mh->OsakVersion, mh->PercentUsed);
 
                if (mh->NoOfBDTLPartitions == 0) {
                        printk(KERN_WARNING "INFTL: Media Header sanity check "
@@ -200,19 +196,15 @@ static int find_boot_record(struct INFTLrecord *inftl)
                        ip->spareUnits = le32_to_cpu(ip->spareUnits);
                        ip->Reserved0 = le32_to_cpu(ip->Reserved0);
 
-#ifdef CONFIG_MTD_DEBUG_VERBOSE
-                       if (CONFIG_MTD_DEBUG_VERBOSE >= 2) {
-                               printk("    PARTITION[%d] ->\n"
-                                       "        virtualUnits    = %d\n"
-                                       "        firstUnit       = %d\n"
-                                       "        lastUnit        = %d\n"
-                                       "        flags           = 0x%x\n"
-                                       "        spareUnits      = %d\n",
-                                       i, ip->virtualUnits, ip->firstUnit,
-                                       ip->lastUnit, ip->flags,
-                                       ip->spareUnits);
-                       }
-#endif
+                       pr_debug("    PARTITION[%d] ->\n"
+                                "        virtualUnits    = %d\n"
+                                "        firstUnit       = %d\n"
+                                "        lastUnit        = %d\n"
+                                "        flags           = 0x%x\n"
+                                "        spareUnits      = %d\n",
+                                i, ip->virtualUnits, ip->firstUnit,
+                                ip->lastUnit, ip->flags,
+                                ip->spareUnits);
 
                        if (ip->Reserved0 != ip->firstUnit) {
                                struct erase_info *instr = &inftl->instr;
@@ -375,7 +367,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
  *
  * Return: 0 when succeed, -1 on error.
  *
- * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
+ * ToDo: 1. Is it necessary to check_free_sector after erasing ??
  */
 int INFTL_formatblock(struct INFTLrecord *inftl, int block)
 {
@@ -385,8 +377,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
        struct mtd_info *mtd = inftl->mbd.mtd;
        int physblock;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p,"
-               "block=%d)\n", inftl, block);
+       pr_debug("INFTL: INFTL_formatblock(inftl=%p,block=%d)\n", inftl, block);
 
        memset(instr, 0, sizeof(struct erase_info));
 
@@ -476,30 +467,30 @@ void INFTL_dumptables(struct INFTLrecord *s)
 {
        int i;
 
-       printk("-------------------------------------------"
+       pr_debug("-------------------------------------------"
                "----------------------------------\n");
 
-       printk("VUtable[%d] ->", s->nb_blocks);
+       pr_debug("VUtable[%d] ->", s->nb_blocks);
        for (i = 0; i < s->nb_blocks; i++) {
                if ((i % 8) == 0)
-                       printk("\n%04x: ", i);
-               printk("%04x ", s->VUtable[i]);
+                       pr_debug("\n%04x: ", i);
+               pr_debug("%04x ", s->VUtable[i]);
        }
 
-       printk("\n-------------------------------------------"
+       pr_debug("\n-------------------------------------------"
                "----------------------------------\n");
 
-       printk("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
+       pr_debug("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
        for (i = 0; i <= s->lastEUN; i++) {
                if ((i % 8) == 0)
-                       printk("\n%04x: ", i);
-               printk("%04x ", s->PUtable[i]);
+                       pr_debug("\n%04x: ", i);
+               pr_debug("%04x ", s->PUtable[i]);
        }
 
-       printk("\n-------------------------------------------"
+       pr_debug("\n-------------------------------------------"
                "----------------------------------\n");
 
-       printk("INFTL ->\n"
+       pr_debug("INFTL ->\n"
                "  EraseSize       = %d\n"
                "  h/s/c           = %d/%d/%d\n"
                "  numvunits       = %d\n"
@@ -513,7 +504,7 @@ void INFTL_dumptables(struct INFTLrecord *s)
                s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
                s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
 
-       printk("\n-------------------------------------------"
+       pr_debug("\n-------------------------------------------"
                "----------------------------------\n");
 }
 
@@ -521,25 +512,25 @@ void INFTL_dumpVUchains(struct INFTLrecord *s)
 {
        int logical, block, i;
 
-       printk("-------------------------------------------"
+       pr_debug("-------------------------------------------"
                "----------------------------------\n");
 
-       printk("INFTL Virtual Unit Chains:\n");
+       pr_debug("INFTL Virtual Unit Chains:\n");
        for (logical = 0; logical < s->nb_blocks; logical++) {
                block = s->VUtable[logical];
                if (block > s->nb_blocks)
                        continue;
-               printk("  LOGICAL %d --> %d ", logical, block);
+               pr_debug("  LOGICAL %d --> %d ", logical, block);
                for (i = 0; i < s->nb_blocks; i++) {
                        if (s->PUtable[block] == BLOCK_NIL)
                                break;
                        block = s->PUtable[block];
-                       printk("%d ", block);
+                       pr_debug("%d ", block);
                }
-               printk("\n");
+               pr_debug("\n");
        }
 
-       printk("-------------------------------------------"
+       pr_debug("-------------------------------------------"
                "----------------------------------\n");
 }
 
@@ -555,7 +546,7 @@ int INFTL_mount(struct INFTLrecord *s)
        int i;
        u8 *ANACtable, ANAC;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=%p)\n", s);
+       pr_debug("INFTL: INFTL_mount(inftl=%p)\n", s);
 
        /* Search for INFTL MediaHeader and Spare INFTL Media Header */
        if (find_boot_record(s) < 0) {
@@ -585,7 +576,7 @@ int INFTL_mount(struct INFTLrecord *s)
         * NOTEXPLORED state. Then at the end we will try to format it and
         * mark it as free.
         */
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 1, explore each unit\n");
+       pr_debug("INFTL: pass 1, explore each unit\n");
        for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {
                if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)
                        continue;
@@ -717,17 +708,14 @@ int INFTL_mount(struct INFTLrecord *s)
                logical_block = BLOCK_NIL;
        }
 
-#ifdef CONFIG_MTD_DEBUG_VERBOSE
-       if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
-               INFTL_dumptables(s);
-#endif
+       INFTL_dumptables(s);
 
        /*
         * Second pass, check for infinite loops in chains. These are
         * possible because we don't update the previous pointers when
         * we fold chains. No big deal, just fix them up in PUtable.
         */
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 2, validate virtual chains\n");
+       pr_debug("INFTL: pass 2, validate virtual chains\n");
        for (logical_block = 0; logical_block < s->numvunits; logical_block++) {
                block = s->VUtable[logical_block];
                last_block = BLOCK_NIL;
@@ -772,12 +760,8 @@ int INFTL_mount(struct INFTLrecord *s)
                }
        }
 
-#ifdef CONFIG_MTD_DEBUG_VERBOSE
-       if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
-               INFTL_dumptables(s);
-       if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
-               INFTL_dumpVUchains(s);
-#endif
+       INFTL_dumptables(s);
+       INFTL_dumpVUchains(s);
 
        /*
         * Third pass, format unreferenced blocks and init free block count.
@@ -785,7 +769,7 @@ int INFTL_mount(struct INFTLrecord *s)
        s->numfreeEUNs = 0;
        s->LastFreeEUN = BLOCK_NIL;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 3, format unused blocks\n");
+       pr_debug("INFTL: pass 3, format unused blocks\n");
        for (block = s->firstEUN; block <= s->lastEUN; block++) {
                if (s->PUtable[block] == BLOCK_NOTEXPLORED) {
                        printk("INFTL: unreferenced block %d, formatting it\n",
index c0c328c5b133ccf51785a19385ae7a48a747aeaf..8e0c4bf9f7fb4e3b2a56f75b540ea8355d01c9c9 100644 (file)
@@ -41,8 +41,6 @@ config MTD_PHYSMAP_START
          are mapped on your particular target board. Refer to the
          memory map which should hopefully be in the documentation for
          your board.
-         Ignore this option if you use run-time physmap configuration
-         (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_LEN
        hex "Physical length of flash mapping"
@@ -55,8 +53,6 @@ config MTD_PHYSMAP_LEN
          than the total amount of flash present. Refer to the memory
          map which should hopefully be in the documentation for your
          board.
-         Ignore this option if you use run-time physmap configuration
-         (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_BANKWIDTH
        int "Bank width in octets"
@@ -67,8 +63,6 @@ config MTD_PHYSMAP_BANKWIDTH
          in octets. For example, if you have a data bus width of 32
          bits, you would set the bus width octet value to 4. This is
          used internally by the CFI drivers.
-         Ignore this option if you use run-time physmap configuration
-         (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_OF
        tristate "Flash device in physical memory map based on OF description"
@@ -260,7 +254,6 @@ config MTD_BCM963XX
 config MTD_LANTIQ
        tristate "Lantiq SoC NOR support"
        depends on LANTIQ
-       select MTD_PARTITIONS
        help
          Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
 
@@ -339,10 +332,6 @@ config MTD_SOLUTIONENGINE
          This enables access to the flash chips on the Hitachi SolutionEngine and
          similar boards. Say 'Y' if you are building a kernel for such a board.
 
-config MTD_ARM_INTEGRATOR
-       tristate "CFI Flash device mapped on ARM Integrator/P720T"
-       depends on ARM && MTD_CFI
-
 config MTD_CDB89712
        tristate "Cirrus CDB89712 evaluation board mappings"
        depends on MTD_CFI && ARCH_CDB89712
@@ -398,13 +387,6 @@ config MTD_AUTCPU12
          This enables access to the NV-RAM on autronix autcpu12 board.
          If you have such a board, say 'Y'.
 
-config MTD_EDB7312
-       tristate "CFI Flash device mapped on EDB7312"
-       depends on ARCH_EDB7312 && MTD_CFI
-       help
-         This enables access to the CFI Flash on the Cogent EDB7312 board.
-         If you have such a board, say 'Y' here.
-
 config MTD_IMPA7
        tristate "JEDEC Flash device mapped on impA7"
        depends on ARM && MTD_JEDECPROBE
@@ -412,14 +394,6 @@ config MTD_IMPA7
          This enables access to the NOR Flash on the impA7 board of
          implementa GmbH. If you have such a board, say 'Y' here.
 
-config MTD_CEIVA
-       tristate "JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame"
-       depends on MTD_JEDECPROBE && ARCH_CEIVA
-       help
-         This enables access to the flash chips on the Ceiva/Polaroid
-         PhotoMax Digital Picture Frame.
-         If you have such a device, say 'Y'.
-
 config MTD_H720X
        tristate "Hynix evaluation board mappings"
        depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
index cb48b11affff8aef535ac93cc96a936e85cd8c32..45dcb8b14f22f0b0cb3b4ed4d7ce85d447c4da79 100644 (file)
@@ -19,7 +19,6 @@ obj-$(CONFIG_MTD_CK804XROM)   += ck804xrom.o
 obj-$(CONFIG_MTD_TSUNAMI)      += tsunami_flash.o
 obj-$(CONFIG_MTD_PXA2XX)       += pxa2xx-flash.o
 obj-$(CONFIG_MTD_MBX860)       += mbx860.o
-obj-$(CONFIG_MTD_CEIVA)                += ceiva.o
 obj-$(CONFIG_MTD_OCTAGON)      += octagon-5066.o
 obj-$(CONFIG_MTD_PHYSMAP)      += physmap.o
 obj-$(CONFIG_MTD_PHYSMAP_OF)   += physmap_of.o
@@ -40,7 +39,6 @@ obj-$(CONFIG_MTD_DBOX2)               += dbox2-flash.o
 obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)          += pci.o
 obj-$(CONFIG_MTD_AUTCPU12)     += autcpu12-nvram.o
-obj-$(CONFIG_MTD_EDB7312)      += edb7312.o
 obj-$(CONFIG_MTD_IMPA7)                += impa7.o
 obj-$(CONFIG_MTD_FORTUNET)     += fortunet.o
 obj-$(CONFIG_MTD_UCLINUX)      += uclinux.o
index 608967fe74c63b73c74268bed8306b1bba6a2079..736ca10ca9f11c0323d6062ef235f42a91f00727 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
index 67815eed2f0039b94a8e86301cf21bc4b88b9df5..6d6b2b5674ee6f4f27282e8356b301446a66c3eb 100644 (file)
@@ -41,7 +41,6 @@ struct async_state {
        uint32_t flash_ambctl0, flash_ambctl1;
        uint32_t save_ambctl0, save_ambctl1;
        unsigned long irq_flags;
-       struct mtd_partition *parts;
 };
 
 static void switch_to_flash(struct async_state *state)
@@ -165,18 +164,8 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
-       if (ret > 0) {
-               pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
-               mtd_device_register(state->mtd, pdata->parts, ret);
-               state->parts = pdata->parts;
-       } else if (pdata->nr_parts) {
-               pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
-               mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts);
-       } else {
-               pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
-               mtd_device_register(state->mtd, NULL, 0);
-       }
+       mtd_device_parse_register(state->mtd, part_probe_types, 0,
+                       pdata->parts, pdata->nr_parts);
 
        platform_set_drvdata(pdev, state);
 
@@ -188,7 +177,6 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev)
        struct async_state *state = platform_get_drvdata(pdev);
        gpio_free(state->enet_flash_pin);
        mtd_device_unregister(state->mtd);
-       kfree(state->parts);
        map_destroy(state->mtd);
        kfree(state);
        return 0;
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
deleted file mode 100644 (file)
index 06f9c98..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Ceiva flash memory driver.
- * Copyright (C) 2002 Rob Scott <rscott@mtrob.fdns.net>
- *
- * Note: this driver supports jedec compatible devices. Modification
- * for CFI compatible devices should be straight forward: change
- * jedec_probe to cfi_probe.
- *
- * Based on: sa1100-flash.c, which has the following copyright:
- * Flash memory access on SA11x0 based devices
- *
- * (C) 2000 Nicolas Pitre <nico@fluxnic.net>
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/concat.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-
-/*
- * This isn't complete yet, so...
- */
-#define CONFIG_MTD_CEIVA_STATICMAP
-
-#ifdef CONFIG_MTD_CEIVA_STATICMAP
-/*
- * See include/linux/mtd/partitions.h for definition of the mtd_partition
- * structure.
- *
- * Please note:
- *  1. The flash size given should be the largest flash size that can
- *     be accommodated.
- *
- *  2. The bus width must defined in clps_setup_flash.
- *
- * The MTD layer will detect flash chip aliasing and reduce the size of
- * the map accordingly.
- *
- */
-
-#ifdef CONFIG_ARCH_CEIVA
-/* Flash / Partition sizing */
-/* For the 28F8003, we use the block mapping to calcuate the sizes */
-#define MAX_SIZE_KiB                  (16 + 8 + 8 + 96 + (7*128))
-#define BOOT_PARTITION_SIZE_KiB       (16)
-#define PARAMS_PARTITION_SIZE_KiB     (8)
-#define KERNEL_PARTITION_SIZE_KiB     (4*128)
-/* Use both remaining portion of first flash, and all of second flash */
-#define ROOT_PARTITION_SIZE_KiB       (3*128) + (8*128)
-
-static struct mtd_partition ceiva_partitions[] = {
-       {
-               .name = "Ceiva BOOT partition",
-               .size   = BOOT_PARTITION_SIZE_KiB*1024,
-               .offset = 0,
-
-       },{
-               .name = "Ceiva parameters partition",
-               .size   = PARAMS_PARTITION_SIZE_KiB*1024,
-               .offset = (16 + 8) * 1024,
-       },{
-               .name = "Ceiva kernel partition",
-               .size = (KERNEL_PARTITION_SIZE_KiB)*1024,
-               .offset = 0x20000,
-
-       },{
-               .name = "Ceiva root filesystem partition",
-               .offset = MTDPART_OFS_APPEND,
-               .size = (ROOT_PARTITION_SIZE_KiB)*1024,
-       }
-};
-#endif
-
-static int __init clps_static_partitions(struct mtd_partition **parts)
-{
-       int nb_parts = 0;
-
-#ifdef CONFIG_ARCH_CEIVA
-       if (machine_is_ceiva()) {
-               *parts       = ceiva_partitions;
-               nb_parts     = ARRAY_SIZE(ceiva_partitions);
-       }
-#endif
-       return nb_parts;
-}
-#endif
-
-struct clps_info {
-       unsigned long base;
-       unsigned long size;
-       int width;
-       void *vbase;
-       struct map_info *map;
-       struct mtd_info *mtd;
-       struct resource *res;
-};
-
-#define NR_SUBMTD 4
-
-static struct clps_info info[NR_SUBMTD];
-
-static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info **rmtd)
-{
-       struct mtd_info *subdev[nr];
-       struct map_info *maps;
-       int i, found = 0, ret = 0;
-
-       /*
-        * Allocate the map_info structs in one go.
-        */
-       maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
-       if (!maps)
-               return -ENOMEM;
-       /*
-        * Claim and then map the memory regions.
-        */
-       for (i = 0; i < nr; i++) {
-               if (clps[i].base == (unsigned long)-1)
-                       break;
-
-               clps[i].res = request_mem_region(clps[i].base, clps[i].size, "clps flash");
-               if (!clps[i].res) {
-                       ret = -EBUSY;
-                       break;
-               }
-
-               clps[i].map = maps + i;
-
-               clps[i].map->name = "clps flash";
-               clps[i].map->phys = clps[i].base;
-
-               clps[i].vbase = ioremap(clps[i].base, clps[i].size);
-               if (!clps[i].vbase) {
-                       ret = -ENOMEM;
-                       break;
-               }
-
-               clps[i].map->virt = (void __iomem *)clps[i].vbase;
-               clps[i].map->bankwidth = clps[i].width;
-               clps[i].map->size = clps[i].size;
-
-               simple_map_init(&clps[i].map);
-
-               clps[i].mtd = do_map_probe("jedec_probe", clps[i].map);
-               if (clps[i].mtd == NULL) {
-                       ret = -ENXIO;
-                       break;
-               }
-               clps[i].mtd->owner = THIS_MODULE;
-               subdev[i] = clps[i].mtd;
-
-               printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, "
-                       "%d-bit\n", clps[i].base, clps[i].mtd->size >> 20,
-                       clps[i].width * 8);
-               found += 1;
-       }
-
-       /*
-        * ENXIO is special.  It means we didn't find a chip when
-        * we probed.  We need to tear down the mapping, free the
-        * resource and mark it as such.
-        */
-       if (ret == -ENXIO) {
-               iounmap(clps[i].vbase);
-               clps[i].vbase = NULL;
-               release_resource(clps[i].res);
-               clps[i].res = NULL;
-       }
-
-       /*
-        * If we found one device, don't bother with concat support.
-        * If we found multiple devices, use concat if we have it
-        * available, otherwise fail.
-        */
-       if (ret == 0 || ret == -ENXIO) {
-               if (found == 1) {
-                       *rmtd = subdev[0];
-                       ret = 0;
-               } else if (found > 1) {
-                       /*
-                        * We detected multiple devices.  Concatenate
-                        * them together.
-                        */
-                       *rmtd = mtd_concat_create(subdev, found,
-                                                 "clps flash");
-                       if (*rmtd == NULL)
-                               ret = -ENXIO;
-               }
-       }
-
-       /*
-        * If we failed, clean up.
-        */
-       if (ret) {
-               do {
-                       if (clps[i].mtd)
-                               map_destroy(clps[i].mtd);
-                       if (clps[i].vbase)
-                               iounmap(clps[i].vbase);
-                       if (clps[i].res)
-                               release_resource(clps[i].res);
-               } while (i--);
-
-               kfree(maps);
-       }
-
-       return ret;
-}
-
-static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd)
-{
-       int i;
-
-       mtd_device_unregister(mtd);
-
-       if (mtd != clps[0].mtd)
-               mtd_concat_destroy(mtd);
-
-       for (i = NR_SUBMTD; i >= 0; i--) {
-               if (clps[i].mtd)
-                       map_destroy(clps[i].mtd);
-               if (clps[i].vbase)
-                       iounmap(clps[i].vbase);
-               if (clps[i].res)
-                       release_resource(clps[i].res);
-       }
-       kfree(clps[0].map);
-}
-
-/*
- * We define the memory space, size, and width for the flash memory
- * space here.
- */
-
-static int __init clps_setup_flash(void)
-{
-       int nr = 0;
-
-#ifdef CONFIG_ARCH_CEIVA
-       if (machine_is_ceiva()) {
-               info[0].base = CS0_PHYS_BASE;
-               info[0].size = SZ_32M;
-               info[0].width = CEIVA_FLASH_WIDTH;
-               info[1].base = CS1_PHYS_BASE;
-               info[1].size = SZ_32M;
-               info[1].width = CEIVA_FLASH_WIDTH;
-               nr = 2;
-       }
-#endif
-       return nr;
-}
-
-static struct mtd_partition *parsed_parts;
-static const char *probes[] = { "cmdlinepart", "RedBoot", NULL };
-
-static void __init clps_locate_partitions(struct mtd_info *mtd)
-{
-       const char *part_type = NULL;
-       int nr_parts = 0;
-       do {
-               /*
-                * Partition selection stuff.
-                */
-               nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0);
-               if (nr_parts > 0) {
-                       part_type = "command line";
-                       break;
-               }
-#ifdef CONFIG_MTD_CEIVA_STATICMAP
-               nr_parts = clps_static_partitions(&parsed_parts);
-               if (nr_parts > 0) {
-                       part_type = "static";
-                       break;
-               }
-               printk("found: %d partitions\n", nr_parts);
-#endif
-       } while (0);
-
-       if (nr_parts == 0) {
-               printk(KERN_NOTICE "clps flash: no partition info "
-                       "available, registering whole flash\n");
-               mtd_device_register(mtd, NULL, 0);
-       } else {
-               printk(KERN_NOTICE "clps flash: using %s partition "
-                       "definition\n", part_type);
-               mtd_device_register(mtd, parsed_parts, nr_parts);
-       }
-
-       /* Always succeeds. */
-}
-
-static void __exit clps_destroy_partitions(void)
-{
-       kfree(parsed_parts);
-}
-
-static struct mtd_info *mymtd;
-
-static int __init clps_mtd_init(void)
-{
-       int ret;
-       int nr;
-
-       nr = clps_setup_flash();
-       if (nr < 0)
-               return nr;
-
-       ret = clps_setup_mtd(info, nr, &mymtd);
-       if (ret)
-               return ret;
-
-       clps_locate_partitions(mymtd);
-
-       return 0;
-}
-
-static void __exit clps_mtd_cleanup(void)
-{
-       clps_destroy_mtd(info, mymtd);
-       clps_destroy_partitions();
-}
-
-module_init(clps_mtd_init);
-module_exit(clps_mtd_cleanup);
-
-MODULE_AUTHOR("Rob Scott");
-MODULE_DESCRIPTION("Cirrus Logic JEDEC map driver");
-MODULE_LICENSE("GPL");
index 7a9e1989c977a1c77694daead3cfd5b62013cb0d..f43b365b848c41ebf2e1a8614762de835b84bbbe 100644 (file)
@@ -145,14 +145,10 @@ static struct map_info dc21285_map = {
 
 
 /* Partition stuff */
-static struct mtd_partition *dc21285_parts;
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int __init init_dc21285(void)
 {
-
-       int nrparts;
-
        /* Determine bankwidth */
        switch (*CSR_SA110_CNTL & (3<<14)) {
                case SA110_CNTL_ROMWIDTH_8:
@@ -200,8 +196,7 @@ static int __init init_dc21285(void)
 
        dc21285_mtd->owner = THIS_MODULE;
 
-       nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0);
-       mtd_device_register(dc21285_mtd, dc21285_parts, nrparts);
+       mtd_device_parse_register(dc21285_mtd, probes, 0, NULL, 0);
 
        if(machine_is_ebsa285()) {
                /*
@@ -224,8 +219,6 @@ static int __init init_dc21285(void)
 static void __exit cleanup_dc21285(void)
 {
        mtd_device_unregister(dc21285_mtd);
-       if (dc21285_parts)
-               kfree(dc21285_parts);
        map_destroy(dc21285_mtd);
        iounmap(dc21285_map.virt);
 }
diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
deleted file mode 100644 (file)
index fe42a21..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Handle mapping of the NOR flash on Cogent EDB7312 boards
- *
- * Copyright 2002 SYSGO Real-Time Solutions GmbH
- *
- * 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/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#define WINDOW_ADDR 0x00000000      /* physical properties of flash */
-#define WINDOW_SIZE 0x01000000
-#define BUSWIDTH    2
-#define FLASH_BLOCKSIZE_MAIN   0x20000
-#define FLASH_NUMBLOCKS_MAIN   128
-/* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */
-#define PROBETYPES { "cfi_probe", NULL }
-
-#define MSG_PREFIX "EDB7312-NOR:"   /* prefix for our printk()'s */
-#define MTDID      "edb7312-nor"    /* for mtdparts= partitioning */
-
-static struct mtd_info *mymtd;
-
-struct map_info edb7312nor_map = {
-       .name = "NOR flash on EDB7312",
-       .size = WINDOW_SIZE,
-       .bankwidth = BUSWIDTH,
-       .phys = WINDOW_ADDR,
-};
-
-/*
- * MTD partitioning stuff
- */
-static struct mtd_partition static_partitions[3] =
-{
-       {
-               .name = "ARMboot",
-               .size = 0x40000,
-               .offset = 0
-       },
-       {
-               .name = "Kernel",
-               .size = 0x200000,
-               .offset = 0x40000
-       },
-       {
-               .name = "RootFS",
-               .size = 0xDC0000,
-               .offset = 0x240000
-       },
-};
-
-static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
-
-static int                   mtd_parts_nb = 0;
-static struct mtd_partition *mtd_parts    = 0;
-
-static int __init init_edb7312nor(void)
-{
-       static const char *rom_probe_types[] = PROBETYPES;
-       const char **type;
-       const char *part_type = 0;
-
-               printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n",
-              WINDOW_SIZE, WINDOW_ADDR);
-       edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
-
-       if (!edb7312nor_map.virt) {
-               printk(MSG_PREFIX "failed to ioremap\n");
-               return -EIO;
-       }
-
-       simple_map_init(&edb7312nor_map);
-
-       mymtd = 0;
-       type = rom_probe_types;
-       for(; !mymtd && *type; type++) {
-               mymtd = do_map_probe(*type, &edb7312nor_map);
-       }
-       if (mymtd) {
-               mymtd->owner = THIS_MODULE;
-
-               mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);
-               if (mtd_parts_nb > 0)
-                       part_type = "detected";
-
-               if (mtd_parts_nb == 0) {
-                       mtd_parts = static_partitions;
-                       mtd_parts_nb = ARRAY_SIZE(static_partitions);
-                       part_type = "static";
-               }
-
-               if (mtd_parts_nb == 0)
-                       printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
-               else
-                       printk(KERN_NOTICE MSG_PREFIX
-                              "using %s partition definition\n", part_type);
-               /* Register the whole device first. */
-               mtd_device_register(mymtd, NULL, 0);
-               mtd_device_register(mymtd, mtd_parts, mtd_parts_nb);
-               return 0;
-       }
-
-       iounmap((void *)edb7312nor_map.virt);
-       return -ENXIO;
-}
-
-static void __exit cleanup_edb7312nor(void)
-{
-       if (mymtd) {
-               mtd_device_unregister(mymtd);
-               map_destroy(mymtd);
-       }
-       if (edb7312nor_map.virt) {
-               iounmap((void *)edb7312nor_map.virt);
-               edb7312nor_map.virt = 0;
-       }
-}
-
-module_init(init_edb7312nor);
-module_exit(cleanup_edb7312nor);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
-MODULE_DESCRIPTION("Generic configurable MTD map driver");
index 7568c5f8b8ae648cb88754e94b34e03ec19c2d65..1ec66f031c51655bb4904c985565f47fc2fc3bfe 100644 (file)
@@ -187,7 +187,6 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
  */
 static int __devinit gpio_flash_probe(struct platform_device *pdev)
 {
-       int nr_parts;
        size_t i, arr_size;
        struct physmap_flash_data *pdata;
        struct resource *memory;
@@ -252,20 +251,9 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       nr_parts = parse_mtd_partitions(state->mtd, part_probe_types,
-                                       &pdata->parts, 0);
-       if (nr_parts > 0) {
-               pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n");
-               kfree(pdata->parts);
-       } else if (pdata->nr_parts) {
-               pr_devinit(KERN_NOTICE PFX "Using board partition definition\n");
-               nr_parts = pdata->nr_parts;
-       } else {
-               pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n");
-               nr_parts = 0;
-       }
 
-       mtd_device_register(state->mtd, pdata->parts, nr_parts);
+       mtd_device_parse_register(state->mtd, part_probe_types, 0,
+                       pdata->parts, pdata->nr_parts);
 
        return 0;
 }
index 7f035860a36bd43b8683945804fee50690f32351..49c14187fc66dc0e469f071db2971d2c0ca4be10 100644 (file)
@@ -58,18 +58,11 @@ static struct mtd_partition h720x_partitions[] = {
 
 #define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions)
 
-static int                   nr_mtd_parts;
-static struct mtd_partition *mtd_parts;
-static const char *probes[] = { "cmdlinepart", NULL };
-
 /*
  * Initialize FLASH support
  */
 static int __init h720x_mtd_init(void)
 {
-
-       char    *part_type = NULL;
-
        h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
 
        if (!h720x_map.virt) {
@@ -92,16 +85,8 @@ static int __init h720x_mtd_init(void)
        if (mymtd) {
                mymtd->owner = THIS_MODULE;
 
-               nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
-               if (nr_mtd_parts > 0)
-                       part_type = "command line";
-               if (nr_mtd_parts <= 0) {
-                       mtd_parts = h720x_partitions;
-                       nr_mtd_parts = NUM_PARTITIONS;
-                       part_type = "builtin";
-               }
-               printk(KERN_INFO "Using %s partition table\n", part_type);
-               mtd_device_register(mymtd, mtd_parts, nr_mtd_parts);
+               mtd_device_parse_register(mymtd, NULL, 0,
+                               h720x_partitions, NUM_PARTITIONS);
                return 0;
        }
 
@@ -120,10 +105,6 @@ static void __exit h720x_mtd_cleanup(void)
                map_destroy(mymtd);
        }
 
-       /* Free partition info, if commandline partition was used */
-       if (mtd_parts && (mtd_parts != h720x_partitions))
-               kfree (mtd_parts);
-
        if (h720x_map.virt) {
                iounmap((void *)h720x_map.virt);
                h720x_map.virt = 0;
index 404a50cbafa0596ef7ea8d2e0d760607d90bf3df..f47aedb24366bb0f1073a1d6c5803a103f029709 100644 (file)
@@ -49,7 +49,7 @@ static struct map_info impa7_map[NUM_FLASHBANKS] = {
 /*
  * MTD partitioning stuff
  */
-static struct mtd_partition static_partitions[] =
+static struct mtd_partition partitions[] =
 {
        {
                .name = "FileSystem",
@@ -58,16 +58,10 @@ static struct mtd_partition static_partitions[] =
        },
 };
 
-static int mtd_parts_nb[NUM_FLASHBANKS];
-static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
-
-static const char *probes[] = { "cmdlinepart", NULL };
-
 static int __init init_impa7(void)
 {
        static const char *rom_probe_types[] = PROBETYPES;
        const char **type;
-       const char *part_type = 0;
        int i;
        static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
          { WINDOW_ADDR0, WINDOW_SIZE0 },
@@ -97,23 +91,9 @@ static int __init init_impa7(void)
                if (impa7_mtd[i]) {
                        impa7_mtd[i]->owner = THIS_MODULE;
                        devicesfound++;
-                       mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
-                                                              probes,
-                                                              &mtd_parts[i],
-                                                              0);
-                       if (mtd_parts_nb[i] > 0) {
-                               part_type = "command line";
-                       } else {
-                               mtd_parts[i] = static_partitions;
-                               mtd_parts_nb[i] = ARRAY_SIZE(static_partitions);
-                               part_type = "static";
-                       }
-
-                       printk(KERN_NOTICE MSG_PREFIX
-                              "using %s partition definition\n",
-                              part_type);
-                       mtd_device_register(impa7_mtd[i],
-                                           mtd_parts[i], mtd_parts_nb[i]);
+                       mtd_device_parse_register(impa7_mtd[i], NULL, 0,
+                                                 partitions,
+                                                 ARRAY_SIZE(partitions));
                }
                else
                        iounmap((void *)impa7_map[i].virt);
index d2f47be8754b211392c0841fd32685396878481a..08c239604ee44e1b71438feda4d30f065b0663f6 100644 (file)
@@ -44,7 +44,6 @@ struct vr_nor_mtd {
        void __iomem *csr_base;
        struct map_info map;
        struct mtd_info *info;
-       int nr_parts;
        struct pci_dev *dev;
 };
 
@@ -71,13 +70,9 @@ static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
 
 static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
 {
-       struct mtd_partition *parts;
-       static const char *part_probes[] = { "cmdlinepart", NULL };
-
        /* register the flash bank */
        /* partition the flash bank */
-       p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0);
-       return mtd_device_register(p->info, parts, p->nr_parts);
+       return mtd_device_parse_register(p->info, NULL, 0, NULL, 0);
 }
 
 static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
index 1594a802631d439f008c58b601e5c29ab6d14a21..437fcd2f352f8095b658cc4a9d1ef28cc01eddf5 100644 (file)
@@ -38,7 +38,6 @@
 struct ixp2000_flash_info {
        struct          mtd_info *mtd;
        struct          map_info map;
-       struct          mtd_partition *partitions;
        struct          resource *res;
 };
 
@@ -125,8 +124,6 @@ static int ixp2000_flash_remove(struct platform_device *dev)
        if (info->map.map_priv_1)
                iounmap((void *) info->map.map_priv_1);
 
-       kfree(info->partitions);
-
        if (info->res) {
                release_resource(info->res);
                kfree(info->res);
@@ -229,13 +226,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
        }
        info->mtd->owner = THIS_MODULE;
 
-       err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
-       if (err > 0) {
-               err = mtd_device_register(info->mtd, info->partitions, err);
-               if(err)
-                       dev_err(&dev->dev, "Could not parse partitions\n");
-       }
-
+       err = mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
        if (err)
                goto Error;
 
index 155b21942f4777a1aea10a8a22b04778ca82ec33..30409015a3de1d67e9d37c2ce345b0a837a28006 100644 (file)
@@ -145,7 +145,6 @@ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 struct ixp4xx_flash_info {
        struct mtd_info *mtd;
        struct map_info map;
-       struct mtd_partition *partitions;
        struct resource *res;
 };
 
@@ -168,8 +167,6 @@ static int ixp4xx_flash_remove(struct platform_device *dev)
        if (info->map.virt)
                iounmap(info->map.virt);
 
-       kfree(info->partitions);
-
        if (info->res) {
                release_resource(info->res);
                kfree(info->res);
@@ -185,8 +182,6 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 {
        struct flash_platform_data *plat = dev->dev.platform_data;
        struct ixp4xx_flash_info *info;
-       const char *part_type = NULL;
-       int nr_parts = 0;
        int err = -1;
 
        if (!plat)
@@ -252,28 +247,12 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
        /* Use the fast version */
        info->map.write = ixp4xx_write16;
 
-       nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
-                                       dev->resource->start);
-       if (nr_parts > 0) {
-               part_type = "dynamic";
-       } else {
-               info->partitions = plat->parts;
-               nr_parts = plat->nr_parts;
-               part_type = "static";
-       }
-       if (nr_parts == 0)
-               printk(KERN_NOTICE "IXP4xx flash: no partition info "
-                       "available, registering whole flash\n");
-       else
-               printk(KERN_NOTICE "IXP4xx flash: using %s partition "
-                       "definition\n", part_type);
-
-       err = mtd_device_register(info->mtd, info->partitions, nr_parts);
-       if (err)
+       err = mtd_device_parse_register(info->mtd, probes, dev->resource->start,
+                       plat->parts, plat->nr_parts);
+       if (err) {
                printk(KERN_ERR "Could not parse partitions\n");
-
-       if (err)
                goto Error;
+       }
 
        return 0;
 
index 7e508969239e92060e3e3818840756cf0f9c2a4a..4f10e27ada551d12f77cfd4d72b02f15ef9c5c8d 100644 (file)
@@ -107,16 +107,12 @@ ltq_copy_to(struct map_info *map, unsigned long to,
        spin_unlock_irqrestore(&ebu_lock, flags);
 }
 
-static const char const *part_probe_types[] = { "cmdlinepart", NULL };
-
 static int __init
 ltq_mtd_probe(struct platform_device *pdev)
 {
        struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
        struct ltq_mtd *ltq_mtd;
-       struct mtd_partition *parts;
        struct resource *res;
-       int nr_parts = 0;
        struct cfi_private *cfi;
        int err;
 
@@ -172,17 +168,8 @@ ltq_mtd_probe(struct platform_device *pdev)
        cfi->addr_unlock1 ^= 1;
        cfi->addr_unlock2 ^= 1;
 
-       nr_parts = parse_mtd_partitions(ltq_mtd->mtd,
-                               part_probe_types, &parts, 0);
-       if (nr_parts > 0) {
-               dev_info(&pdev->dev,
-                       "using %d partitions from cmdline", nr_parts);
-       } else {
-               nr_parts = ltq_mtd_data->nr_parts;
-               parts = ltq_mtd_data->parts;
-       }
-
-       err = mtd_device_register(ltq_mtd->mtd, parts, nr_parts);
+       err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0,
+                       ltq_mtd_data->parts, ltq_mtd_data->nr_parts);
        if (err) {
                dev_err(&pdev->dev, "failed to add partitions\n");
                goto err_destroy;
index 5936c466e901369be6b0d7a9a13c4330fe78fcdc..119baa7d74773088ea0f07ffd316b6ee2c807b7d 100644 (file)
@@ -33,9 +33,6 @@ struct latch_addr_flash_info {
        /* cache; could be found out of res */
        unsigned long           win_mask;
 
-       int                     nr_parts;
-       struct mtd_partition    *parts;
-
        spinlock_t              lock;
 };
 
@@ -97,8 +94,6 @@ static void lf_copy_from(struct map_info *map, void *to,
 
 static char *rom_probe_types[] = { "cfi_probe", NULL };
 
-static char *part_probe_types[] = { "cmdlinepart", NULL };
-
 static int latch_addr_flash_remove(struct platform_device *dev)
 {
        struct latch_addr_flash_info *info;
@@ -112,8 +107,6 @@ static int latch_addr_flash_remove(struct platform_device *dev)
        latch_addr_data = dev->dev.platform_data;
 
        if (info->mtd != NULL) {
-               if (info->nr_parts)
-                       kfree(info->parts);
                mtd_device_unregister(info->mtd);
                map_destroy(info->mtd);
        }
@@ -206,21 +199,8 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev)
        }
        info->mtd->owner = THIS_MODULE;
 
-       err = parse_mtd_partitions(info->mtd, (const char **)part_probe_types,
-                                  &info->parts, 0);
-       if (err > 0) {
-               mtd_device_register(info->mtd, info->parts, err);
-               return 0;
-       }
-       if (latch_addr_data->nr_parts) {
-               pr_notice("Using latch-addr-flash partition information\n");
-               mtd_device_register(info->mtd,
-                                   latch_addr_data->parts,
-                                   latch_addr_data->nr_parts);
-               return 0;
-       }
-
-       mtd_device_register(info->mtd, NULL, 0);
+       mtd_device_parse_register(info->mtd, NULL, 0,
+                       latch_addr_data->parts, latch_addr_data->nr_parts);
        return 0;
 
 iounmap:
index bbe168b65c26a392e09bc8bdb4783b2d5c7ab06f..e8e9fec23553d06ea34410633c12c8cce558fdb2 100644 (file)
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 
-#ifdef CONFIG_MTD_DEBUG
-static int debug = CONFIG_MTD_DEBUG_VERBOSE;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
-#undef DEBUG
-#define DEBUG(n, format, arg...) \
-       if (n <= debug) {        \
-               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
-       }
-
-#else
-#undef DEBUG
-#define DEBUG(n, arg...)
-static const int debug = 0;
-#endif
-
 #define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
 
 #define DRIVER_DESC    "PCMCIA Flash memory card driver"
@@ -105,13 +89,13 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
        int ret;
 
        if (!pcmcia_dev_present(dev->p_dev)) {
-               DEBUG(1, "device removed");
+               pr_debug("device removed\n");
                return 0;
        }
 
        offset = to & ~(dev->win_size-1);
        if (offset != dev->offset) {
-               DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
+               pr_debug("Remapping window from 0x%8.8x to 0x%8.8x\n",
                      dev->offset, offset);
                ret = pcmcia_map_mem_page(dev->p_dev, win, offset);
                if (ret != 0)
@@ -132,7 +116,7 @@ static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
                return d;
 
        d.x[0] = readb(addr);
-       DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, addr, d.x[0]);
+       pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n", ofs, addr, d.x[0]);
        return d;
 }
 
@@ -147,7 +131,7 @@ static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
                return d;
 
        d.x[0] = readw(addr);
-       DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, addr, d.x[0]);
+       pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n", ofs, addr, d.x[0]);
        return d;
 }
 
@@ -157,7 +141,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
        unsigned long win_size = dev->win_size;
 
-       DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
+       pr_debug("to = %p from = %lu len = %zd\n", to, from, len);
        while(len) {
                int toread = win_size - (from & (win_size-1));
                caddr_t addr;
@@ -169,7 +153,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long
                if(!addr)
                        return;
 
-               DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread);
+               pr_debug("memcpy from %p to %p len = %d\n", addr, to, toread);
                memcpy_fromio(to, addr, toread);
                len -= toread;
                to += toread;
@@ -185,7 +169,7 @@ static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long
        if(!addr)
                return;
 
-       DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02lx", adr, addr, d.x[0]);
+       pr_debug("adr = 0x%08lx (%p)  data = 0x%02lx\n", adr, addr, d.x[0]);
        writeb(d.x[0], addr);
 }
 
@@ -196,7 +180,7 @@ static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long
        if(!addr)
                return;
 
-       DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04lx", adr, addr, d.x[0]);
+       pr_debug("adr = 0x%08lx (%p)  data = 0x%04lx\n", adr, addr, d.x[0]);
        writew(d.x[0], addr);
 }
 
@@ -206,7 +190,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
        unsigned long win_size = dev->win_size;
 
-       DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
+       pr_debug("to = %lu from = %p len = %zd\n", to, from, len);
        while(len) {
                int towrite = win_size - (to & (win_size-1));
                caddr_t addr;
@@ -218,7 +202,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
                if(!addr)
                        return;
 
-               DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite);
+               pr_debug("memcpy from %p to %p len = %d\n", from, addr, towrite);
                memcpy_toio(addr, from, towrite);
                len -= towrite;
                to += towrite;
@@ -240,7 +224,7 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
                return d;
 
        d.x[0] = readb(win_base + ofs);
-       DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx",
+       pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n",
              ofs, win_base + ofs, d.x[0]);
        return d;
 }
@@ -255,7 +239,7 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
                return d;
 
        d.x[0] = readw(win_base + ofs);
-       DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx",
+       pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n",
              ofs, win_base + ofs, d.x[0]);
        return d;
 }
@@ -268,7 +252,7 @@ static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from,
        if(DEV_REMOVED(map))
                return;
 
-       DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
+       pr_debug("to = %p from = %lu len = %zd\n", to, from, len);
        memcpy_fromio(to, win_base + from, len);
 }
 
@@ -280,7 +264,7 @@ static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr)
        if(DEV_REMOVED(map))
                return;
 
-       DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02lx",
+       pr_debug("adr = 0x%08lx (%p)  data = 0x%02lx\n",
              adr, win_base + adr, d.x[0]);
        writeb(d.x[0], win_base + adr);
 }
@@ -293,7 +277,7 @@ static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr)
        if(DEV_REMOVED(map))
                return;
 
-       DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04lx",
+       pr_debug("adr = 0x%08lx (%p)  data = 0x%04lx\n",
              adr, win_base + adr, d.x[0]);
        writew(d.x[0], win_base + adr);
 }
@@ -306,7 +290,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f
        if(DEV_REMOVED(map))
                return;
 
-       DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
+       pr_debug("to = %lu from = %p len = %zd\n", to, from, len);
        memcpy_toio(win_base + to, from, len);
 }
 
@@ -316,7 +300,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
        struct pcmcia_device *link = dev->p_dev;
 
-       DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
+       pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp);
        pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
 }
 
@@ -325,7 +309,7 @@ static void pcmciamtd_release(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev = link->priv;
 
-       DEBUG(3, "link = 0x%p", link);
+       pr_debug("link = 0x%p\n", link);
 
        if (link->resource[2]->end) {
                if(dev->win_base) {
@@ -337,7 +321,6 @@ static void pcmciamtd_release(struct pcmcia_device *link)
 }
 
 
-#ifdef CONFIG_MTD_DEBUG
 static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
                                tuple_t *tuple,
                                void *priv_data)
@@ -347,7 +330,7 @@ static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
        if (!pcmcia_parse_tuple(tuple, &parse)) {
                cistpl_format_t *t = &parse.format;
                (void)t; /* Shut up, gcc */
-               DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",
+               pr_debug("Format type: %u, Error Detection: %u, offset = %u, length =%u\n",
                        t->type, t->edc, t->offset, t->length);
        }
        return -ENOSPC;
@@ -363,12 +346,11 @@ static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev,
        if (!pcmcia_parse_tuple(tuple, &parse)) {
                cistpl_jedec_t *t = &parse.jedec;
                for (i = 0; i < t->nid; i++)
-                       DEBUG(2, "JEDEC: 0x%02x 0x%02x",
+                       pr_debug("JEDEC: 0x%02x 0x%02x\n",
                              t->id[i].mfr, t->id[i].info);
        }
        return -ENOSPC;
 }
-#endif
 
 static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
                                tuple_t *tuple,
@@ -382,14 +364,14 @@ static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
        if (pcmcia_parse_tuple(tuple, &parse))
                return -EINVAL;
 
-       DEBUG(2, "Common memory:");
+       pr_debug("Common memory:\n");
        dev->pcmcia_map.size = t->dev[0].size;
        /* from here on: DEBUG only */
        for (i = 0; i < t->ndev; i++) {
-               DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);
-               DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);
-               DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);
-               DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);
+               pr_debug("Region %d, type = %u\n", i, t->dev[i].type);
+               pr_debug("Region %d, wp = %u\n", i, t->dev[i].wp);
+               pr_debug("Region %d, speed = %u ns\n", i, t->dev[i].speed);
+               pr_debug("Region %d, size = %u bytes\n", i, t->dev[i].size);
        }
        return 0;
 }
@@ -409,12 +391,12 @@ static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev,
        dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
        /* from here on: DEBUG only */
        for (i = 0; i < t->ngeo; i++) {
-               DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);
-               DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
-               DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
-               DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
-               DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition);
-               DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave);
+               pr_debug("region: %d bankwidth = %u\n", i, t->geo[i].buswidth);
+               pr_debug("region: %d erase_block = %u\n", i, t->geo[i].erase_block);
+               pr_debug("region: %d read_block = %u\n", i, t->geo[i].read_block);
+               pr_debug("region: %d write_block = %u\n", i, t->geo[i].write_block);
+               pr_debug("region: %d partition = %u\n", i, t->geo[i].partition);
+               pr_debug("region: %d interleave = %u\n", i, t->geo[i].interleave);
        }
        return 0;
 }
@@ -432,13 +414,11 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev
                        if (p_dev->prod_id[i])
                                strcat(dev->mtd_name, p_dev->prod_id[i]);
                }
-               DEBUG(2, "Found name: %s", dev->mtd_name);
+               pr_debug("Found name: %s\n", dev->mtd_name);
        }
 
-#ifdef CONFIG_MTD_DEBUG
        pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL);
        pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL);
-#endif
        pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev);
        pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev);
 
@@ -450,12 +430,12 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev
 
        if(force_size) {
                dev->pcmcia_map.size = force_size << 20;
-               DEBUG(2, "size forced to %dM", force_size);
+               pr_debug("size forced to %dM\n", force_size);
        }
 
        if(bankwidth) {
                dev->pcmcia_map.bankwidth = bankwidth;
-               DEBUG(2, "bankwidth forced to %d", bankwidth);
+               pr_debug("bankwidth forced to %d\n", bankwidth);
        }
 
        dev->pcmcia_map.name = dev->mtd_name;
@@ -464,7 +444,7 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev
                *new_name = 1;
        }
 
-       DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
+       pr_debug("Device: Size: %lu Width:%d Name: %s\n",
              dev->pcmcia_map.size,
              dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
 }
@@ -479,7 +459,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        static char *probes[] = { "jedec_probe", "cfi_probe" };
        int new_name = 0;
 
-       DEBUG(3, "link=0x%p", link);
+       pr_debug("link=0x%p\n", link);
 
        card_settings(dev, link, &new_name);
 
@@ -512,11 +492,11 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 
        do {
                int ret;
-               DEBUG(2, "requesting window with size = %luKiB memspeed = %d",
+               pr_debug("requesting window with size = %luKiB memspeed = %d\n",
                        (unsigned long) resource_size(link->resource[2]) >> 10,
                        mem_speed);
                ret = pcmcia_request_window(link, link->resource[2], mem_speed);
-               DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
+               pr_debug("ret = %d dev->win_size = %d\n", ret, dev->win_size);
                if(ret) {
                        j++;
                        link->resource[2]->start = 0;
@@ -524,21 +504,21 @@ static int pcmciamtd_config(struct pcmcia_device *link)
                                        force_size << 20 : MAX_PCMCIA_ADDR;
                        link->resource[2]->end >>= j;
                } else {
-                       DEBUG(2, "Got window of size %luKiB", (unsigned long)
+                       pr_debug("Got window of size %luKiB\n", (unsigned long)
                                resource_size(link->resource[2]) >> 10);
                        dev->win_size = resource_size(link->resource[2]);
                        break;
                }
        } while (link->resource[2]->end >= 0x1000);
 
-       DEBUG(2, "dev->win_size = %d", dev->win_size);
+       pr_debug("dev->win_size = %d\n", dev->win_size);
 
        if(!dev->win_size) {
                dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
                pcmciamtd_release(link);
                return -ENODEV;
        }
-       DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
+       pr_debug("Allocated a window of %dKiB\n", dev->win_size >> 10);
 
        /* Get write protect status */
        dev->win_base = ioremap(link->resource[2]->start,
@@ -549,7 +529,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
                pcmciamtd_release(link);
                return -ENODEV;
        }
-       DEBUG(1, "mapped window dev = %p @ %pR, base = %p",
+       pr_debug("mapped window dev = %p @ %pR, base = %p\n",
              dev, link->resource[2], dev->win_base);
 
        dev->offset = 0;
@@ -564,7 +544,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        }
 
        link->config_index = 0;
-       DEBUG(2, "Setting Configuration");
+       pr_debug("Setting Configuration\n");
        ret = pcmcia_enable_device(link);
        if (ret != 0) {
                if (dev->win_base) {
@@ -580,17 +560,17 @@ static int pcmciamtd_config(struct pcmcia_device *link)
                mtd = do_map_probe("map_rom", &dev->pcmcia_map);
        } else {
                for(i = 0; i < ARRAY_SIZE(probes); i++) {
-                       DEBUG(1, "Trying %s", probes[i]);
+                       pr_debug("Trying %s\n", probes[i]);
                        mtd = do_map_probe(probes[i], &dev->pcmcia_map);
                        if(mtd)
                                break;
 
-                       DEBUG(1, "FAILED: %s", probes[i]);
+                       pr_debug("FAILED: %s\n", probes[i]);
                }
        }
 
        if(!mtd) {
-               DEBUG(1, "Can not find an MTD");
+               pr_debug("Can not find an MTD\n");
                pcmciamtd_release(link);
                return -ENODEV;
        }
@@ -617,7 +597,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        /* If the memory found is fits completely into the mapped PCMCIA window,
           use the faster non-remapping read/write functions */
        if(mtd->size <= dev->win_size) {
-               DEBUG(1, "Using non remapping memory functions");
+               pr_debug("Using non remapping memory functions\n");
                dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
                if (dev->pcmcia_map.bankwidth == 1) {
                        dev->pcmcia_map.read = pcmcia_read8;
@@ -645,7 +625,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 
 static int pcmciamtd_suspend(struct pcmcia_device *dev)
 {
-       DEBUG(2, "EVENT_PM_RESUME");
+       pr_debug("EVENT_PM_RESUME\n");
 
        /* get_lock(link); */
 
@@ -654,7 +634,7 @@ static int pcmciamtd_suspend(struct pcmcia_device *dev)
 
 static int pcmciamtd_resume(struct pcmcia_device *dev)
 {
-       DEBUG(2, "EVENT_PM_SUSPEND");
+       pr_debug("EVENT_PM_SUSPEND\n");
 
        /* free_lock(link); */
 
@@ -666,7 +646,7 @@ static void pcmciamtd_detach(struct pcmcia_device *link)
 {
        struct pcmciamtd_dev *dev = link->priv;
 
-       DEBUG(3, "link=0x%p", link);
+       pr_debug("link=0x%p\n", link);
 
        if(dev->mtd_info) {
                mtd_device_unregister(dev->mtd_info);
@@ -686,7 +666,7 @@ static int pcmciamtd_probe(struct pcmcia_device *link)
        /* Create new memory card device */
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev) return -ENOMEM;
-       DEBUG(1, "dev=0x%p", dev);
+       pr_debug("dev=0x%p\n", dev);
 
        dev->p_dev = link;
        link->priv = dev;
@@ -755,7 +735,7 @@ static int __init init_pcmciamtd(void)
 
 static void __exit exit_pcmciamtd(void)
 {
-       DEBUG(1, DRIVER_DESC " unloading");
+       pr_debug(DRIVER_DESC " unloading");
        pcmcia_unregister_driver(&pcmciamtd_driver);
 }
 
index f64cee4a3bfbeba9674fea84c4465e645d925594..66e8200079c2c25633db8f662967825575b89915 100644 (file)
@@ -27,8 +27,6 @@ struct physmap_flash_info {
        struct mtd_info         *mtd[MAX_RESOURCES];
        struct mtd_info         *cmtd;
        struct map_info         map[MAX_RESOURCES];
-       int                     nr_parts;
-       struct mtd_partition    *parts;
 };
 
 static int physmap_flash_remove(struct platform_device *dev)
@@ -46,8 +44,6 @@ static int physmap_flash_remove(struct platform_device *dev)
 
        if (info->cmtd) {
                mtd_device_unregister(info->cmtd);
-               if (info->nr_parts)
-                       kfree(info->parts);
                if (info->cmtd != info->mtd[0])
                        mtd_concat_destroy(info->cmtd);
        }
@@ -175,23 +171,8 @@ static int physmap_flash_probe(struct platform_device *dev)
        if (err)
                goto err_out;
 
-       err = parse_mtd_partitions(info->cmtd, part_probe_types,
-                                  &info->parts, 0);
-       if (err > 0) {
-               mtd_device_register(info->cmtd, info->parts, err);
-               info->nr_parts = err;
-               return 0;
-       }
-
-       if (physmap_data->nr_parts) {
-               printk(KERN_NOTICE "Using physmap partition information\n");
-               mtd_device_register(info->cmtd, physmap_data->parts,
-                                   physmap_data->nr_parts);
-               return 0;
-       }
-
-       mtd_device_register(info->cmtd, NULL, 0);
-
+       mtd_device_parse_register(info->cmtd, part_probe_types, 0,
+                                 physmap_data->parts, physmap_data->nr_parts);
        return 0;
 
 err_out:
@@ -245,21 +226,6 @@ static struct platform_device physmap_flash = {
        .num_resources  = 1,
        .resource       = &physmap_flash_resource,
 };
-
-void physmap_configure(unsigned long addr, unsigned long size,
-               int bankwidth, void (*set_vpp)(struct map_info *, int))
-{
-       physmap_flash_resource.start = addr;
-       physmap_flash_resource.end = addr + size - 1;
-       physmap_flash_data.width = bankwidth;
-       physmap_flash_data.set_vpp = set_vpp;
-}
-
-void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
-{
-       physmap_flash_data.nr_parts = num_parts;
-       physmap_flash_data.parts = parts;
-}
 #endif
 
 static int __init physmap_init(void)
index d251d1db129b3fd81391302b1add42b0052e869d..7d65f9d3e6902e442003dfd7455953d1199c2d9a 100644 (file)
@@ -34,58 +34,10 @@ struct of_flash_list {
 
 struct of_flash {
        struct mtd_info         *cmtd;
-       struct mtd_partition    *parts;
        int list_size; /* number of elements in of_flash_list */
        struct of_flash_list    list[0];
 };
 
-#define OF_FLASH_PARTS(info)   ((info)->parts)
-static int parse_obsolete_partitions(struct platform_device *dev,
-                                    struct of_flash *info,
-                                    struct device_node *dp)
-{
-       int i, plen, nr_parts;
-       const struct {
-               __be32 offset, len;
-       } *part;
-       const char *names;
-
-       part = of_get_property(dp, "partitions", &plen);
-       if (!part)
-               return 0; /* No partitions found */
-
-       dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
-
-       nr_parts = plen / sizeof(part[0]);
-
-       info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
-       if (!info->parts)
-               return -ENOMEM;
-
-       names = of_get_property(dp, "partition-names", &plen);
-
-       for (i = 0; i < nr_parts; i++) {
-               info->parts[i].offset = be32_to_cpu(part->offset);
-               info->parts[i].size   = be32_to_cpu(part->len) & ~1;
-               if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
-                       info->parts[i].mask_flags = MTD_WRITEABLE;
-
-               if (names && (plen > 0)) {
-                       int len = strlen(names) + 1;
-
-                       info->parts[i].name = (char *)names;
-                       plen -= len;
-                       names += len;
-               } else {
-                       info->parts[i].name = "unnamed";
-               }
-
-               part++;
-       }
-
-       return nr_parts;
-}
-
 static int of_flash_remove(struct platform_device *dev)
 {
        struct of_flash *info;
@@ -101,11 +53,8 @@ static int of_flash_remove(struct platform_device *dev)
                mtd_concat_destroy(info->cmtd);
        }
 
-       if (info->cmtd) {
-               if (OF_FLASH_PARTS(info))
-                       kfree(OF_FLASH_PARTS(info));
+       if (info->cmtd)
                mtd_device_unregister(info->cmtd);
-       }
 
        for (i = 0; i < info->list_size; i++) {
                if (info->list[i].mtd)
@@ -165,7 +114,8 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
    information. */
-static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
+static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
+                                       "ofpart", "ofoldpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
        const char *cp;
@@ -218,6 +168,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
        int reg_tuple_size;
        struct mtd_info **mtd_list = NULL;
        resource_size_t res_size;
+       struct mtd_part_parser_data ppdata;
 
        match = of_match_device(of_flash_match, &dev->dev);
        if (!match)
@@ -331,29 +282,12 @@ static int __devinit of_flash_probe(struct platform_device *dev)
        if (err)
                goto err_out;
 
+       ppdata.of_node = dp;
        part_probe_types = of_get_probes(dp);
-       err = parse_mtd_partitions(info->cmtd, part_probe_types,
-                                  &info->parts, 0);
-       if (err < 0) {
-               of_free_probes(part_probe_types);
-               goto err_out;
-       }
+       mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
+                       NULL, 0);
        of_free_probes(part_probe_types);
 
-       if (err == 0) {
-               err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
-               if (err < 0)
-                       goto err_out;
-       }
-
-       if (err == 0) {
-               err = parse_obsolete_partitions(dev, info, dp);
-               if (err < 0)
-                       goto err_out;
-       }
-
-       mtd_device_register(info->cmtd, info->parts, err);
-
        kfree(mtd_list);
 
        return 0;
index 9ca1eccba4bc2e70b0d5e7ea6c3be5d014f6da5e..94f553489725280d2ec851023f17745e86c48d9a 100644 (file)
@@ -44,8 +44,6 @@ struct platram_info {
        struct device           *dev;
        struct mtd_info         *mtd;
        struct map_info          map;
-       struct mtd_partition    *partitions;
-       bool                    free_partitions;
        struct resource         *area;
        struct platdata_mtd_ram *pdata;
 };
@@ -95,10 +93,6 @@ static int platram_remove(struct platform_device *pdev)
 
        if (info->mtd) {
                mtd_device_unregister(info->mtd);
-               if (info->partitions) {
-                       if (info->free_partitions)
-                               kfree(info->partitions);
-               }
                map_destroy(info->mtd);
        }
 
@@ -228,21 +222,8 @@ static int platram_probe(struct platform_device *pdev)
        /* check to see if there are any available partitions, or wether
         * to add this device whole */
 
-       if (!pdata->nr_partitions) {
-               /* try to probe using the supplied probe type */
-               if (pdata->probes) {
-                       err = parse_mtd_partitions(info->mtd, pdata->probes,
-                                          &info->partitions, 0);
-                       info->free_partitions = 1;
-                       if (err > 0)
-                               err = mtd_device_register(info->mtd,
-                                       info->partitions, err);
-               }
-       }
-       /* use the static mapping */
-       else
-               err = mtd_device_register(info->mtd, pdata->partitions,
-                                         pdata->nr_partitions);
+       err = mtd_device_parse_register(info->mtd, pdata->probes, 0,
+                       pdata->partitions, pdata->nr_partitions);
        if (!err)
                dev_info(&pdev->dev, "registered mtd device\n");
 
index 7ae137d4b99871bbbe94f6b11effa25b5537875d..411a17df9fc13ee2fd78d8e54456e18095bdd91f 100644 (file)
@@ -41,8 +41,6 @@ static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from,
 }
 
 struct pxa2xx_flash_info {
-       struct mtd_partition    *parts;
-       int                     nr_parts;
        struct mtd_info         *mtd;
        struct map_info         map;
 };
@@ -55,9 +53,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 {
        struct flash_platform_data *flash = pdev->dev.platform_data;
        struct pxa2xx_flash_info *info;
-       struct mtd_partition *parts;
        struct resource *res;
-       int ret = 0;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
@@ -71,8 +67,6 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
        info->map.bankwidth = flash->width;
        info->map.phys = res->start;
        info->map.size = resource_size(res);
-       info->parts = flash->parts;
-       info->nr_parts = flash->nr_parts;
 
        info->map.virt = ioremap(info->map.phys, info->map.size);
        if (!info->map.virt) {
@@ -104,18 +98,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
        }
        info->mtd->owner = THIS_MODULE;
 
-       ret = parse_mtd_partitions(info->mtd, probes, &parts, 0);
-
-       if (ret > 0) {
-               info->nr_parts = ret;
-               info->parts = parts;
-       }
-
-       if (!info->nr_parts)
-               printk("Registering %s as whole device\n",
-                      info->map.name);
-
-       mtd_device_register(info->mtd, info->parts, info->nr_parts);
+       mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
 
        platform_set_drvdata(pdev, info);
        return 0;
@@ -133,7 +116,6 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
        iounmap(info->map.virt);
        if (info->map.cached)
                iounmap(info->map.cached);
-       kfree(info->parts);
        kfree(info);
        return 0;
 }
index 761fb459d2c74179105fb9ded586681c66ae6aae..0237f197fd1238f553732f73a2db64ddba98c0f6 100644 (file)
@@ -25,8 +25,6 @@
 struct rbtx4939_flash_info {
        struct mtd_info *mtd;
        struct map_info map;
-       int nr_parts;
-       struct mtd_partition *parts;
 };
 
 static int rbtx4939_flash_remove(struct platform_device *dev)
@@ -41,8 +39,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
        if (info->mtd) {
                struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
 
-               if (info->nr_parts)
-                       kfree(info->parts);
                mtd_device_unregister(info->mtd);
                map_destroy(info->mtd);
        }
@@ -50,7 +46,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
 }
 
 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
-static const char *part_probe_types[] = { "cmdlinepart", NULL };
 
 static int rbtx4939_flash_probe(struct platform_device *dev)
 {
@@ -107,22 +102,11 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
        info->mtd->owner = THIS_MODULE;
        if (err)
                goto err_out;
+       err = mtd_device_parse_register(info->mtd, NULL, 0,
+                       pdata->parts, pdata->nr_parts);
 
-       err = parse_mtd_partitions(info->mtd, part_probe_types,
-                               &info->parts, 0);
-       if (err > 0) {
-               mtd_device_register(info->mtd, info->parts, err);
-               info->nr_parts = err;
-               return 0;
-       }
-
-       if (pdata->nr_parts) {
-               pr_notice("Using rbtx4939 partition information\n");
-               mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
-               return 0;
-       }
-
-       mtd_device_register(info->mtd, NULL, 0);
+       if (err)
+               goto err_out;
        return 0;
 
 err_out:
index a9b5e0e5c4c559b059842468d5c15a70f0bfc7c3..fa9c0a9670cd88a4e050ba65f0d70f51fee9f3d7 100644 (file)
@@ -131,10 +131,8 @@ struct sa_subdev_info {
 };
 
 struct sa_info {
-       struct mtd_partition    *parts;
        struct mtd_info         *mtd;
        int                     num_subdev;
-       unsigned int            nr_parts;
        struct sa_subdev_info   subdev[0];
 };
 
@@ -231,8 +229,6 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla
                        mtd_concat_destroy(info->mtd);
        }
 
-       kfree(info->parts);
-
        for (i = info->num_subdev - 1; i >= 0; i--)
                sa1100_destroy_subdev(&info->subdev[i]);
        kfree(info);
@@ -341,10 +337,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 {
        struct flash_platform_data *plat = pdev->dev.platform_data;
-       struct mtd_partition *parts;
-       const char *part_type = NULL;
        struct sa_info *info;
-       int err, nr_parts = 0;
+       int err;
 
        if (!plat)
                return -ENODEV;
@@ -358,26 +352,8 @@ static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
        /*
         * Partition selection stuff.
         */
-       nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
-       if (nr_parts > 0) {
-               info->parts = parts;
-               part_type = "dynamic";
-       } else {
-               parts = plat->parts;
-               nr_parts = plat->nr_parts;
-               part_type = "static";
-       }
-
-       if (nr_parts == 0)
-               printk(KERN_NOTICE "SA1100 flash: no partition info "
-                       "available, registering whole flash\n");
-       else
-               printk(KERN_NOTICE "SA1100 flash: using %s partition "
-                       "definition\n", part_type);
-
-       mtd_device_register(info->mtd, parts, nr_parts);
-
-       info->nr_parts = nr_parts;
+       mtd_device_parse_register(info->mtd, part_probes, 0,
+                       plat->parts, plat->nr_parts);
 
        platform_set_drvdata(pdev, info);
        err = 0;
index cbf6bade9354681164e707b2e43924b21a833578..496c40704aff6567dcd7546b0cb9c87742222263 100644 (file)
@@ -19,8 +19,6 @@
 static struct mtd_info *flash_mtd;
 static struct mtd_info *eprom_mtd;
 
-static struct mtd_partition *parsed_parts;
-
 struct map_info soleng_eprom_map = {
        .name = "Solution Engine EPROM",
        .size = 0x400000,
@@ -51,12 +49,14 @@ static struct mtd_partition superh_se_partitions[] = {
                .size = MTDPART_SIZ_FULL,
        }
 };
+#define NUM_PARTITIONS ARRAY_SIZE(superh_se_partitions)
+#else
+#define superh_se_partitions NULL
+#define NUM_PARTITIONS 0
 #endif /* CONFIG_MTD_SUPERH_RESERVE */
 
 static int __init init_soleng_maps(void)
 {
-       int nr_parts = 0;
-
        /* First probe at offset 0 */
        soleng_flash_map.phys = 0;
        soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
@@ -92,21 +92,8 @@ static int __init init_soleng_maps(void)
                mtd_device_register(eprom_mtd, NULL, 0);
        }
 
-       nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
-
-#ifdef CONFIG_MTD_SUPERH_RESERVE
-       if (nr_parts <= 0) {
-               printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
-                      CONFIG_MTD_SUPERH_RESERVE);
-               parsed_parts = superh_se_partitions;
-               nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts);
-       }
-#endif /* CONFIG_MTD_SUPERH_RESERVE */
-
-       if (nr_parts > 0)
-               mtd_device_register(flash_mtd, parsed_parts, nr_parts);
-       else
-               mtd_device_register(flash_mtd, NULL, 0);
+       mtd_device_parse_register(flash_mtd, probes, 0,
+                       superh_se_partitions, NUM_PARTITIONS);
 
        return 0;
 }
@@ -118,10 +105,7 @@ static void __exit cleanup_soleng_maps(void)
                map_destroy(eprom_mtd);
        }
 
-       if (parsed_parts)
-               mtd_device_unregister(flash_mtd);
-       else
-               mtd_device_unregister(flash_mtd);
+       mtd_device_unregister(flash_mtd);
        map_destroy(flash_mtd);
 }
 
index 901ce968efaebc11acf9e9c4e5460dfec7fc3e3d..aa7e0cb2893c791311e71356ec79d074745129a6 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/immap_cpm2.h>
 
 static struct mtd_info *sbcmtd[3];
-static struct mtd_partition *sbcmtd_parts[3];
 
 struct map_info sbc82xx_flash_map[3] = {
        {.name = "Boot flash"},
@@ -101,6 +100,7 @@ static int __init init_sbc82xx_flash(void)
        for (i=0; i<3; i++) {
                int8_t flashcs[3] = { 0, 6, 1 };
                int nr_parts;
+               struct mtd_partition *defparts;
 
                printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
                       sbc82xx_flash_map[i].name,
@@ -113,7 +113,8 @@ static int __init init_sbc82xx_flash(void)
                }
                printk(" at %08lx)\n",  sbc82xx_flash_map[i].phys);
 
-               sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size);
+               sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys,
+                                                   sbc82xx_flash_map[i].size);
 
                if (!sbc82xx_flash_map[i].virt) {
                        printk("Failed to ioremap\n");
@@ -129,24 +130,20 @@ static int __init init_sbc82xx_flash(void)
 
                sbcmtd[i]->owner = THIS_MODULE;
 
-               nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
-                                               &sbcmtd_parts[i], 0);
-               if (nr_parts > 0) {
-                       mtd_device_register(sbcmtd[i], sbcmtd_parts[i],
-                                           nr_parts);
-                       continue;
-               }
-
                /* No partitioning detected. Use default */
                if (i == 2) {
-                       mtd_device_register(sbcmtd[i], NULL, 0);
+                       defparts = NULL;
+                       nr_parts = 0;
                } else if (i == bigflash) {
-                       mtd_device_register(sbcmtd[i], bigflash_parts,
-                                           ARRAY_SIZE(bigflash_parts));
+                       defparts = bigflash_parts;
+                       nr_parts = ARRAY_SIZE(bigflash_parts);
                } else {
-                       mtd_device_register(sbcmtd[i], smallflash_parts,
-                                           ARRAY_SIZE(smallflash_parts));
+                       defparts = smallflash_parts;
+                       nr_parts = ARRAY_SIZE(smallflash_parts);
                }
+
+               mtd_device_parse_register(sbcmtd[i], part_probes, 0,
+                                         defparts, nr_parts);
        }
        return 0;
 }
@@ -159,12 +156,8 @@ static void __exit cleanup_sbc82xx_flash(void)
                if (!sbcmtd[i])
                        continue;
 
-               if (i<2 || sbcmtd_parts[i])
-                       mtd_device_unregister(sbcmtd[i]);
-               else
-                       mtd_device_unregister(sbcmtd[i]);
+               mtd_device_unregister(sbcmtd[i]);
 
-               kfree(sbcmtd_parts[i]);
                map_destroy(sbcmtd[i]);
 
                iounmap((void *)sbc82xx_flash_map[i].virt);
index ca385697446ece7ebfe387a4cd99b41cbca9ebbc..ed8b5e744b12abc15b0db0189c972b3331bd1f0b 100644 (file)
@@ -426,6 +426,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
        new->rq->queuedata = new;
        blk_queue_logical_block_size(new->rq, tr->blksize);
 
+       queue_flag_set_unlocked(QUEUE_FLAG_NONROT, new->rq);
+
        if (tr->discard) {
                queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq);
                new->rq->limits.max_discard_sectors = UINT_MAX;
index 3326615ad66b957c57234bf3eb83699a393ff62e..7c1dc908a17475eeb1f610deb8f36505e5b2e439 100644 (file)
@@ -44,7 +44,7 @@ struct mtdblk_dev {
        enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
 };
 
-static struct mutex mtdblks_lock;
+static DEFINE_MUTEX(mtdblks_lock);
 
 /*
  * Cache stuff...
@@ -119,7 +119,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk)
        if (mtdblk->cache_state != STATE_DIRTY)
                return 0;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" "
+       pr_debug("mtdblock: writing cached data for \"%s\" "
                        "at 0x%lx, size 0x%x\n", mtd->name,
                        mtdblk->cache_offset, mtdblk->cache_size);
 
@@ -148,7 +148,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
        size_t retlen;
        int ret;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",
+       pr_debug("mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",
                mtd->name, pos, len);
 
        if (!sect_size)
@@ -218,7 +218,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
        size_t retlen;
        int ret;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
+       pr_debug("mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
                        mtd->name, pos, len);
 
        if (!sect_size)
@@ -283,7 +283,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
 {
        struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd);
 
-       DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
+       pr_debug("mtdblock_open\n");
 
        mutex_lock(&mtdblks_lock);
        if (mtdblk->count) {
@@ -303,7 +303,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
 
        mutex_unlock(&mtdblks_lock);
 
-       DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
+       pr_debug("ok\n");
 
        return 0;
 }
@@ -312,7 +312,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
 {
        struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd);
 
-       DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
+       pr_debug("mtdblock_release\n");
 
        mutex_lock(&mtdblks_lock);
 
@@ -329,7 +329,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
 
        mutex_unlock(&mtdblks_lock);
 
-       DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
+       pr_debug("ok\n");
 
        return 0;
 }
@@ -389,8 +389,6 @@ static struct mtd_blktrans_ops mtdblock_tr = {
 
 static int __init init_mtdblock(void)
 {
-       mutex_init(&mtdblks_lock);
-
        return register_mtd_blktrans(&mtdblock_tr);
 }
 
index 61086ea3cc6bf7856b138042ea308d8b12af554a..e7dc732ddabc6588226211b8fc23e2799e37d628 100644 (file)
@@ -43,7 +43,7 @@ static struct vfsmount *mtd_inode_mnt __read_mostly;
 
 /*
  * Data structure to hold the pointer to the mtd device as well
- * as mode information ofr various use cases.
+ * as mode information of various use cases.
  */
 struct mtd_file_info {
        struct mtd_info *mtd;
@@ -86,7 +86,7 @@ static int mtd_open(struct inode *inode, struct file *file)
        struct mtd_file_info *mfi;
        struct inode *mtd_ino;
 
-       DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
+       pr_debug("MTD_open\n");
 
        /* You can't open the RO devices RW */
        if ((file->f_mode & FMODE_WRITE) && (minor & 1))
@@ -151,7 +151,7 @@ static int mtd_close(struct inode *inode, struct file *file)
        struct mtd_file_info *mfi = file->private_data;
        struct mtd_info *mtd = mfi->mtd;
 
-       DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
+       pr_debug("MTD_close\n");
 
        /* Only sync if opened RW */
        if ((file->f_mode & FMODE_WRITE) && mtd->sync)
@@ -195,7 +195,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
        size_t size = count;
        char *kbuf;
 
-       DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
+       pr_debug("MTD_read\n");
 
        if (*ppos + count > mtd->size)
                count = mtd->size - *ppos;
@@ -211,17 +211,17 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
                len = min_t(size_t, count, size);
 
                switch (mfi->mode) {
-               case MTD_MODE_OTP_FACTORY:
+               case MTD_FILE_MODE_OTP_FACTORY:
                        ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);
                        break;
-               case MTD_MODE_OTP_USER:
+               case MTD_FILE_MODE_OTP_USER:
                        ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
                        break;
-               case MTD_MODE_RAW:
+               case MTD_FILE_MODE_RAW:
                {
                        struct mtd_oob_ops ops;
 
-                       ops.mode = MTD_OOB_RAW;
+                       ops.mode = MTD_OPS_RAW;
                        ops.datbuf = kbuf;
                        ops.oobbuf = NULL;
                        ops.len = len;
@@ -233,16 +233,16 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
                default:
                        ret = mtd->read(mtd, *ppos, len, &retlen, kbuf);
                }
-               /* Nand returns -EBADMSG on ecc errors, but it returns
+               /* Nand returns -EBADMSG on ECC errors, but it returns
                 * the data. For our userspace tools it is important
-                * to dump areas with ecc errors !
+                * to dump areas with ECC errors!
                 * For kernel internal usage it also might return -EUCLEAN
                 * to signal the caller that a bitflip has occurred and has
                 * been corrected by the ECC algorithm.
                 * Userspace software which accesses NAND this way
                 * must be aware of the fact that it deals with NAND
                 */
-               if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) {
+               if (!ret || mtd_is_bitflip_or_eccerr(ret)) {
                        *ppos += retlen;
                        if (copy_to_user(buf, kbuf, retlen)) {
                                kfree(kbuf);
@@ -278,7 +278,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
        int ret=0;
        int len;
 
-       DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
+       pr_debug("MTD_write\n");
 
        if (*ppos == mtd->size)
                return -ENOSPC;
@@ -302,10 +302,10 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
                }
 
                switch (mfi->mode) {
-               case MTD_MODE_OTP_FACTORY:
+               case MTD_FILE_MODE_OTP_FACTORY:
                        ret = -EROFS;
                        break;
-               case MTD_MODE_OTP_USER:
+               case MTD_FILE_MODE_OTP_USER:
                        if (!mtd->write_user_prot_reg) {
                                ret = -EOPNOTSUPP;
                                break;
@@ -313,13 +313,14 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
                        ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
                        break;
 
-               case MTD_MODE_RAW:
+               case MTD_FILE_MODE_RAW:
                {
                        struct mtd_oob_ops ops;
 
-                       ops.mode = MTD_OOB_RAW;
+                       ops.mode = MTD_OPS_RAW;
                        ops.datbuf = kbuf;
                        ops.oobbuf = NULL;
+                       ops.ooboffs = 0;
                        ops.len = len;
 
                        ret = mtd->write_oob(mtd, *ppos, &ops);
@@ -367,13 +368,13 @@ static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
                if (!mtd->read_fact_prot_reg)
                        ret = -EOPNOTSUPP;
                else
-                       mfi->mode = MTD_MODE_OTP_FACTORY;
+                       mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
                break;
        case MTD_OTP_USER:
                if (!mtd->read_fact_prot_reg)
                        ret = -EOPNOTSUPP;
                else
-                       mfi->mode = MTD_MODE_OTP_USER;
+                       mfi->mode = MTD_FILE_MODE_OTP_USER;
                break;
        default:
                ret = -EINVAL;
@@ -390,6 +391,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
        uint64_t start, uint32_t length, void __user *ptr,
        uint32_t __user *retp)
 {
+       struct mtd_file_info *mfi = file->private_data;
        struct mtd_oob_ops ops;
        uint32_t retlen;
        int ret = 0;
@@ -409,9 +411,10 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
                return ret;
 
        ops.ooblen = length;
-       ops.ooboffs = start & (mtd->oobsize - 1);
+       ops.ooboffs = start & (mtd->writesize - 1);
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
+               MTD_OPS_PLACE_OOB;
 
        if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
                return -EINVAL;
@@ -420,7 +423,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
        if (IS_ERR(ops.oobbuf))
                return PTR_ERR(ops.oobbuf);
 
-       start &= ~((uint64_t)mtd->oobsize - 1);
+       start &= ~((uint64_t)mtd->writesize - 1);
        ret = mtd->write_oob(mtd, start, &ops);
 
        if (ops.oobretlen > 0xFFFFFFFFU)
@@ -433,9 +436,11 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
        return ret;
 }
 
-static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
-       uint32_t length, void __user *ptr, uint32_t __user *retp)
+static int mtd_do_readoob(struct file *file, struct mtd_info *mtd,
+       uint64_t start, uint32_t length, void __user *ptr,
+       uint32_t __user *retp)
 {
+       struct mtd_file_info *mfi = file->private_data;
        struct mtd_oob_ops ops;
        int ret = 0;
 
@@ -451,9 +456,10 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
                return ret;
 
        ops.ooblen = length;
-       ops.ooboffs = start & (mtd->oobsize - 1);
+       ops.ooboffs = start & (mtd->writesize - 1);
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
+               MTD_OPS_PLACE_OOB;
 
        if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
                return -EINVAL;
@@ -462,7 +468,7 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
        if (!ops.oobbuf)
                return -ENOMEM;
 
-       start &= ~((uint64_t)mtd->oobsize - 1);
+       start &= ~((uint64_t)mtd->writesize - 1);
        ret = mtd->read_oob(mtd, start, &ops);
 
        if (put_user(ops.oobretlen, retp))
@@ -472,13 +478,29 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
                ret = -EFAULT;
 
        kfree(ops.oobbuf);
+
+       /*
+        * NAND returns -EBADMSG on ECC errors, but it returns the OOB
+        * data. For our userspace tools it is important to dump areas
+        * with ECC errors!
+        * For kernel internal usage it also might return -EUCLEAN
+        * to signal the caller that a bitflip has occured and has
+        * been corrected by the ECC algorithm.
+        *
+        * Note: currently the standard NAND function, nand_read_oob_std,
+        * does not calculate ECC for the OOB area, so do not rely on
+        * this behavior unless you have replaced it with your own.
+        */
+       if (mtd_is_bitflip_or_eccerr(ret))
+               return 0;
+
        return ret;
 }
 
 /*
  * Copies (and truncates, if necessary) data from the larger struct,
  * nand_ecclayout, to the smaller, deprecated layout struct,
- * nand_ecclayout_user. This is necessary only to suppport the deprecated
+ * nand_ecclayout_user. This is necessary only to support the deprecated
  * API ioctl ECCGETLAYOUT while allowing all new functionality to use
  * nand_ecclayout flexibly (i.e. the struct may change size in new
  * releases without requiring major rewrites).
@@ -544,6 +566,55 @@ static int mtd_blkpg_ioctl(struct mtd_info *mtd,
        }
 }
 
+static int mtd_write_ioctl(struct mtd_info *mtd,
+               struct mtd_write_req __user *argp)
+{
+       struct mtd_write_req req;
+       struct mtd_oob_ops ops;
+       void __user *usr_data, *usr_oob;
+       int ret;
+
+       if (copy_from_user(&req, argp, sizeof(req)) ||
+                       !access_ok(VERIFY_READ, req.usr_data, req.len) ||
+                       !access_ok(VERIFY_READ, req.usr_oob, req.ooblen))
+               return -EFAULT;
+       if (!mtd->write_oob)
+               return -EOPNOTSUPP;
+
+       ops.mode = req.mode;
+       ops.len = (size_t)req.len;
+       ops.ooblen = (size_t)req.ooblen;
+       ops.ooboffs = 0;
+
+       usr_data = (void __user *)(uintptr_t)req.usr_data;
+       usr_oob = (void __user *)(uintptr_t)req.usr_oob;
+
+       if (req.usr_data) {
+               ops.datbuf = memdup_user(usr_data, ops.len);
+               if (IS_ERR(ops.datbuf))
+                       return PTR_ERR(ops.datbuf);
+       } else {
+               ops.datbuf = NULL;
+       }
+
+       if (req.usr_oob) {
+               ops.oobbuf = memdup_user(usr_oob, ops.ooblen);
+               if (IS_ERR(ops.oobbuf)) {
+                       kfree(ops.datbuf);
+                       return PTR_ERR(ops.oobbuf);
+               }
+       } else {
+               ops.oobbuf = NULL;
+       }
+
+       ret = mtd->write_oob(mtd, (loff_t)req.start, &ops);
+
+       kfree(ops.datbuf);
+       kfree(ops.oobbuf);
+
+       return ret;
+}
+
 static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 {
        struct mtd_file_info *mfi = file->private_data;
@@ -553,7 +624,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
        u_long size;
        struct mtd_info_user info;
 
-       DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
+       pr_debug("MTD_ioctl\n");
 
        size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
        if (cmd & IOC_IN) {
@@ -601,8 +672,8 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
                info.erasesize  = mtd->erasesize;
                info.writesize  = mtd->writesize;
                info.oobsize    = mtd->oobsize;
-               /* The below fields are obsolete */
-               info.ecctype    = -1;
+               /* The below field is obsolete */
+               info.padding    = 0;
                if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
                        return -EFAULT;
                break;
@@ -698,7 +769,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
                if (copy_from_user(&buf, argp, sizeof(buf)))
                        ret = -EFAULT;
                else
-                       ret = mtd_do_readoob(mtd, buf.start, buf.length,
+                       ret = mtd_do_readoob(file, mtd, buf.start, buf.length,
                                buf.ptr, &buf_user->start);
                break;
        }
@@ -725,12 +796,19 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
                if (copy_from_user(&buf, argp, sizeof(buf)))
                        ret = -EFAULT;
                else
-                       ret = mtd_do_readoob(mtd, buf.start, buf.length,
+                       ret = mtd_do_readoob(file, mtd, buf.start, buf.length,
                                (void __user *)(uintptr_t)buf.usr_ptr,
                                &buf_user->length);
                break;
        }
 
+       case MEMWRITE:
+       {
+               ret = mtd_write_ioctl(mtd,
+                     (struct mtd_write_req __user *)arg);
+               break;
+       }
+
        case MEMLOCK:
        {
                struct erase_info_user einfo;
@@ -827,7 +905,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
                if (copy_from_user(&mode, argp, sizeof(int)))
                        return -EFAULT;
 
-               mfi->mode = MTD_MODE_NORMAL;
+               mfi->mode = MTD_FILE_MODE_NORMAL;
 
                ret = otp_select_filemode(mfi, mode);
 
@@ -843,11 +921,11 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
                        return -ENOMEM;
                ret = -EOPNOTSUPP;
                switch (mfi->mode) {
-               case MTD_MODE_OTP_FACTORY:
+               case MTD_FILE_MODE_OTP_FACTORY:
                        if (mtd->get_fact_prot_info)
                                ret = mtd->get_fact_prot_info(mtd, buf, 4096);
                        break;
-               case MTD_MODE_OTP_USER:
+               case MTD_FILE_MODE_OTP_USER:
                        if (mtd->get_user_prot_info)
                                ret = mtd->get_user_prot_info(mtd, buf, 4096);
                        break;
@@ -871,7 +949,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
        {
                struct otp_info oinfo;
 
-               if (mfi->mode != MTD_MODE_OTP_USER)
+               if (mfi->mode != MTD_FILE_MODE_OTP_USER)
                        return -EINVAL;
                if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
                        return -EFAULT;
@@ -882,7 +960,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
        }
 #endif
 
-       /* This ioctl is being deprecated - it truncates the ecc layout */
+       /* This ioctl is being deprecated - it truncates the ECC layout */
        case ECCGETLAYOUT:
        {
                struct nand_ecclayout_user *usrlay;
@@ -915,17 +993,17 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
                mfi->mode = 0;
 
                switch(arg) {
-               case MTD_MODE_OTP_FACTORY:
-               case MTD_MODE_OTP_USER:
+               case MTD_FILE_MODE_OTP_FACTORY:
+               case MTD_FILE_MODE_OTP_USER:
                        ret = otp_select_filemode(mfi, arg);
                        break;
 
-               case MTD_MODE_RAW:
+               case MTD_FILE_MODE_RAW:
                        if (!mtd->read_oob || !mtd->write_oob)
                                return -EOPNOTSUPP;
                        mfi->mode = arg;
 
-               case MTD_MODE_NORMAL:
+               case MTD_FILE_MODE_NORMAL:
                        break;
                default:
                        ret = -EINVAL;
@@ -1011,7 +1089,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
                if (copy_from_user(&buf, argp, sizeof(buf)))
                        ret = -EFAULT;
                else
-                       ret = mtd_do_readoob(mtd, buf.start,
+                       ret = mtd_do_readoob(file, mtd, buf.start,
                                buf.length, compat_ptr(buf.ptr),
                                &buf_user->start);
                break;
index e601672a53050900d3d0b8cf084829db6d10d9bd..6df4d4d4eb92bb585c9f0bc08815be208cda2d53 100644 (file)
@@ -95,10 +95,10 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
 
                /* Save information about bitflips! */
                if (unlikely(err)) {
-                       if (err == -EBADMSG) {
+                       if (mtd_is_eccerr(err)) {
                                mtd->ecc_stats.failed++;
                                ret = err;
-                       } else if (err == -EUCLEAN) {
+                       } else if (mtd_is_bitflip(err)) {
                                mtd->ecc_stats.corrected++;
                                /* Do not overwrite -EBADMSG !! */
                                if (!ret)
@@ -279,10 +279,10 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 
                /* Save information about bitflips! */
                if (unlikely(err)) {
-                       if (err == -EBADMSG) {
+                       if (mtd_is_eccerr(err)) {
                                mtd->ecc_stats.failed++;
                                ret = err;
-                       } else if (err == -EUCLEAN) {
+                       } else if (mtd_is_bitflip(err)) {
                                mtd->ecc_stats.corrected++;
                                /* Do not overwrite -EBADMSG !! */
                                if (!ret)
@@ -770,7 +770,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
 
        /*
         * Set up the new "super" device's MTD object structure, check for
-        * incompatibilites between the subdevices.
+        * incompatibilities between the subdevices.
         */
        concat->mtd.type = subdev[0]->type;
        concat->mtd.flags = subdev[0]->flags;
index c510aff289a88d077d9e42c6854bfdcd1533e3be..b01993ea260ef95b064a04763989bc324f61a342 100644 (file)
@@ -362,7 +362,7 @@ int add_mtd_device(struct mtd_info *mtd)
                              MTD_DEVT(i) + 1,
                              NULL, "mtd%dro", i);
 
-       DEBUG(0, "mtd: Giving out device %d to %s\n", i, mtd->name);
+       pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name);
        /* No need to get a refcount on the module containing
           the notifier, since we hold the mtd_table_mutex */
        list_for_each_entry(not, &mtd_notifiers, list)
@@ -429,27 +429,63 @@ out_error:
 }
 
 /**
- * mtd_device_register - register an MTD device.
+ * mtd_device_parse_register - parse partitions and register an MTD device.
  *
- * @master: the MTD device to register
- * @parts: the partitions to register - only valid if nr_parts > 0
- * @nr_parts: the number of partitions in parts.  If zero then the full MTD
- *            device is registered
+ * @mtd: the MTD device to register
+ * @types: the list of MTD partition probes to try, see
+ *         'parse_mtd_partitions()' for more information
+ * @parser_data: MTD partition parser-specific data
+ * @parts: fallback partition information to register, if parsing fails;
+ *         only valid if %nr_parts > %0
+ * @nr_parts: the number of partitions in parts, if zero then the full
+ *            MTD device is registered if no partition info is found
  *
- * Register an MTD device with the system and optionally, a number of
- * partitions.  If nr_parts is 0 then the whole device is registered, otherwise
- * only the partitions are registered.  To register both the full device *and*
- * the partitions, call mtd_device_register() twice, once with nr_parts == 0
- * and once equal to the number of partitions.
+ * This function aggregates MTD partitions parsing (done by
+ * 'parse_mtd_partitions()') and MTD device and partitions registering. It
+ * basically follows the most common pattern found in many MTD drivers:
+ *
+ * * It first tries to probe partitions on MTD device @mtd using parsers
+ *   specified in @types (if @types is %NULL, then the default list of parsers
+ *   is used, see 'parse_mtd_partitions()' for more information). If none are
+ *   found this functions tries to fallback to information specified in
+ *   @parts/@nr_parts.
+ * * If any partitioning info was found, this function registers the found
+ *   partitions.
+ * * If no partitions were found this function just registers the MTD device
+ *   @mtd and exits.
+ *
+ * Returns zero in case of success and a negative error code in case of failure.
  */
-int mtd_device_register(struct mtd_info *master,
-                       const struct mtd_partition *parts,
-                       int nr_parts)
+int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
+                             struct mtd_part_parser_data *parser_data,
+                             const struct mtd_partition *parts,
+                             int nr_parts)
 {
-       return parts ? add_mtd_partitions(master, parts, nr_parts) :
-               add_mtd_device(master);
+       int err;
+       struct mtd_partition *real_parts;
+
+       err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
+       if (err <= 0 && nr_parts && parts) {
+               real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
+                                    GFP_KERNEL);
+               if (!real_parts)
+                       err = -ENOMEM;
+               else
+                       err = nr_parts;
+       }
+
+       if (err > 0) {
+               err = add_mtd_partitions(mtd, real_parts, err);
+               kfree(real_parts);
+       } else if (err == 0) {
+               err = add_mtd_device(mtd);
+               if (err == 1)
+                       err = -ENODEV;
+       }
+
+       return err;
 }
-EXPORT_SYMBOL_GPL(mtd_device_register);
+EXPORT_SYMBOL_GPL(mtd_device_parse_register);
 
 /**
  * mtd_device_unregister - unregister an existing MTD device.
index 0ed6126b4c1ffb0cc40c7f161926daf20d14bb0b..961a38408542b70df255a8ba05871a2ffb43a3fa 100644 (file)
@@ -15,6 +15,9 @@ extern int del_mtd_device(struct mtd_info *mtd);
 extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *,
                              int);
 extern int del_mtd_partitions(struct mtd_info *);
+extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
+                               struct mtd_partition **pparts,
+                               struct mtd_part_parser_data *data);
 
 #define mtd_for_each_device(mtd)                       \
        for ((mtd) = __mtd_next_device(0);              \
index e3e40f4403235540dc5ad5f6e3efd35aa981f647..1e2fa6236705941b9fea37b5f0d5bf4a713e56c7 100644 (file)
@@ -258,7 +258,7 @@ static void find_next_position(struct mtdoops_context *cxt)
                ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
                                &retlen, (u_char *) &count[0]);
                if (retlen != MTDOOPS_HEADER_SIZE ||
-                               (ret < 0 && ret != -EUCLEAN)) {
+                               (ret < 0 && !mtd_is_bitflip(ret))) {
                        printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n",
                               page * record_size, retlen,
                               MTDOOPS_HEADER_SIZE, ret);
index 630be3e7da04f2eed1ab628c21004ba077d4522c..a0bd2de4752baa3981b09a31b1efb0cc5f7b4a8b 100644 (file)
@@ -73,9 +73,9 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
        res = part->master->read(part->master, from + part->offset,
                                   len, retlen, buf);
        if (unlikely(res)) {
-               if (res == -EUCLEAN)
+               if (mtd_is_bitflip(res))
                        mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected;
-               if (res == -EBADMSG)
+               if (mtd_is_eccerr(res))
                        mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed;
        }
        return res;
@@ -130,7 +130,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
        if (ops->oobbuf) {
                size_t len, pages;
 
-               if (ops->mode == MTD_OOB_AUTO)
+               if (ops->mode == MTD_OPS_AUTO_OOB)
                        len = mtd->oobavail;
                else
                        len = mtd->oobsize;
@@ -142,9 +142,9 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
 
        res = part->master->read_oob(part->master, from + part->offset, ops);
        if (unlikely(res)) {
-               if (res == -EUCLEAN)
+               if (mtd_is_bitflip(res))
                        mtd->ecc_stats.corrected++;
-               if (res == -EBADMSG)
+               if (mtd_is_eccerr(res))
                        mtd->ecc_stats.failed++;
        }
        return res;
@@ -479,6 +479,19 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
                               (unsigned long long)cur_offset, (unsigned long long)slave->offset);
                }
        }
+       if (slave->offset == MTDPART_OFS_RETAIN) {
+               slave->offset = cur_offset;
+               if (master->size - slave->offset >= slave->mtd.size) {
+                       slave->mtd.size = master->size - slave->offset
+                                                       - slave->mtd.size;
+               } else {
+                       printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
+                               part->name, master->size - slave->offset,
+                               slave->mtd.size);
+                       /* register to preserve ordering */
+                       goto out_register;
+               }
+       }
        if (slave->mtd.size == MTDPART_SIZ_FULL)
                slave->mtd.size = master->size - slave->offset;
 
@@ -693,6 +706,8 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
        return ret;
 }
 
+#define put_partition_parser(p) do { module_put((p)->owner); } while (0)
+
 int register_mtd_parser(struct mtd_part_parser *p)
 {
        spin_lock(&part_parser_lock);
@@ -712,19 +727,51 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
+/*
+ * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
+ * are changing this array!
+ */
+static const char *default_mtd_part_types[] = {
+       "cmdlinepart",
+       "ofpart",
+       NULL
+};
+
+/**
+ * parse_mtd_partitions - parse MTD partitions
+ * @master: the master partition (describes whole MTD device)
+ * @types: names of partition parsers to try or %NULL
+ * @pparts: array of partitions found is returned here
+ * @data: MTD partition parser-specific data
+ *
+ * This function tries to find partition on MTD device @master. It uses MTD
+ * partition parsers, specified in @types. However, if @types is %NULL, then
+ * the default list of parsers is used. The default list contains only the
+ * "cmdlinepart" and "ofpart" parsers ATM.
+ *
+ * This function may return:
+ * o a negative error code in case of failure
+ * o zero if no partitions were found
+ * o a positive number of found partitions, in which case on exit @pparts will
+ *   point to an array containing this number of &struct mtd_info objects.
+ */
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
-                        struct mtd_partition **pparts, unsigned long origin)
+                        struct mtd_partition **pparts,
+                        struct mtd_part_parser_data *data)
 {
        struct mtd_part_parser *parser;
        int ret = 0;
 
+       if (!types)
+               types = default_mtd_part_types;
+
        for ( ; ret <= 0 && *types; types++) {
                parser = get_partition_parser(*types);
                if (!parser && !request_module("%s", *types))
                                parser = get_partition_parser(*types);
                if (!parser)
                        continue;
-               ret = (*parser->parse_fn)(master, pparts, origin);
+               ret = (*parser->parse_fn)(master, pparts, data);
                if (ret > 0) {
                        printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
                               ret, parser->name, master->name);
@@ -733,7 +780,6 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
        }
        return ret;
 }
-EXPORT_SYMBOL_GPL(parse_mtd_partitions);
 
 int mtd_is_partition(struct mtd_info *mtd)
 {
index 89f8e66448ab9cc1443e05166ab1bd75e7c46dce..a90bfe79916d29c6f7c2460e9dc644dadc46904e 100644 (file)
@@ -27,12 +27,12 @@ static int get_sb_mtd_compare(struct super_block *sb, void *_mtd)
        struct mtd_info *mtd = _mtd;
 
        if (sb->s_mtd == mtd) {
-               DEBUG(2, "MTDSB: Match on device %d (\"%s\")\n",
+               pr_debug("MTDSB: Match on device %d (\"%s\")\n",
                      mtd->index, mtd->name);
                return 1;
        }
 
-       DEBUG(2, "MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
+       pr_debug("MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
              sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name);
        return 0;
 }
@@ -71,7 +71,7 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
                goto already_mounted;
 
        /* fresh new superblock */
-       DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n",
+       pr_debug("MTDSB: New superblock for device %d (\"%s\")\n",
              mtd->index, mtd->name);
 
        sb->s_flags = flags;
@@ -88,7 +88,7 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
 
        /* new mountpoint for an already mounted superblock */
 already_mounted:
-       DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n",
+       pr_debug("MTDSB: Device %d (\"%s\") is already mounted\n",
              mtd->index, mtd->name);
        put_mtd_device(mtd);
        return dget(sb->s_root);
@@ -109,7 +109,7 @@ static struct dentry *mount_mtd_nr(struct file_system_type *fs_type, int flags,
 
        mtd = get_mtd_device(NULL, mtdnr);
        if (IS_ERR(mtd)) {
-               DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
+               pr_debug("MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
                return ERR_CAST(mtd);
        }
 
@@ -132,7 +132,7 @@ struct dentry *mount_mtd(struct file_system_type *fs_type, int flags,
        if (!dev_name)
                return ERR_PTR(-EINVAL);
 
-       DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name);
+       pr_debug("MTDSB: dev_name \"%s\"\n", dev_name);
 
        /* the preferred way of mounting in future; especially when
         * CONFIG_BLOCK=n - we specify the underlying MTD device by number or
@@ -143,7 +143,7 @@ struct dentry *mount_mtd(struct file_system_type *fs_type, int flags,
                        struct mtd_info *mtd;
 
                        /* mount by MTD device name */
-                       DEBUG(1, "MTDSB: mtd:%%s, name \"%s\"\n",
+                       pr_debug("MTDSB: mtd:%%s, name \"%s\"\n",
                              dev_name + 4);
 
                        mtd = get_mtd_device_nm(dev_name + 4);
@@ -164,7 +164,7 @@ struct dentry *mount_mtd(struct file_system_type *fs_type, int flags,
                        mtdnr = simple_strtoul(dev_name + 3, &endptr, 0);
                        if (!*endptr) {
                                /* It was a valid number */
-                               DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n",
+                               pr_debug("MTDSB: mtd%%d, mtdnr %d\n",
                                      mtdnr);
                                return mount_mtd_nr(fs_type, flags,
                                                     dev_name, data,
@@ -180,10 +180,10 @@ struct dentry *mount_mtd(struct file_system_type *fs_type, int flags,
        bdev = lookup_bdev(dev_name);
        if (IS_ERR(bdev)) {
                ret = PTR_ERR(bdev);
-               DEBUG(1, "MTDSB: lookup_bdev() returned %d\n", ret);
+               pr_debug("MTDSB: lookup_bdev() returned %d\n", ret);
                return ERR_PTR(ret);
        }
-       DEBUG(1, "MTDSB: lookup_bdev() returned 0\n");
+       pr_debug("MTDSB: lookup_bdev() returned 0\n");
 
        ret = -EINVAL;
 
index fd7885327611d75d68a25e788fa7a44950109513..bd9590c723e41fcbb7055cc4dc61f49f402e340d 100644 (file)
@@ -86,7 +86,7 @@ struct swap_eb {
        unsigned int flags;
        unsigned int active_count;
        unsigned int erase_count;
-       unsigned int pad;               /* speeds up pointer decremtnt */
+       unsigned int pad;               /* speeds up pointer decrement */
 };
 
 #define MTDSWAP_ECNT_MIN(rbroot) (rb_entry(rb_first(rbroot), struct swap_eb, \
@@ -314,7 +314,7 @@ static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from,
 {
        int ret = d->mtd->read_oob(d->mtd, from, ops);
 
-       if (ret == -EUCLEAN)
+       if (mtd_is_bitflip(ret))
                return ret;
 
        if (ret) {
@@ -350,11 +350,11 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb)
        ops.oobbuf = d->oob_buf;
        ops.ooboffs = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_AUTO;
+       ops.mode = MTD_OPS_AUTO_OOB;
 
        ret = mtdswap_read_oob(d, offset, &ops);
 
-       if (ret && ret != -EUCLEAN)
+       if (ret && !mtd_is_bitflip(ret))
                return ret;
 
        data = (struct mtdswap_oobdata *)d->oob_buf;
@@ -363,7 +363,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb)
 
        if (le16_to_cpu(data->magic) == MTDSWAP_MAGIC_CLEAN) {
                eb->erase_count = le32_to_cpu(data->count);
-               if (ret == -EUCLEAN)
+               if (mtd_is_bitflip(ret))
                        ret = MTDSWAP_SCANNED_BITFLIP;
                else {
                        if (le16_to_cpu(data2->magic) == MTDSWAP_MAGIC_DIRTY)
@@ -389,7 +389,7 @@ static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb,
 
        ops.ooboffs = 0;
        ops.oobbuf = (uint8_t *)&n;
-       ops.mode = MTD_OOB_AUTO;
+       ops.mode = MTD_OPS_AUTO_OOB;
        ops.datbuf = NULL;
 
        if (marker == MTDSWAP_TYPE_CLEAN) {
@@ -408,7 +408,7 @@ static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb,
        if (ret) {
                dev_warn(d->dev, "Write OOB failed for block at %08llx "
                        "error %d\n", offset, ret);
-               if (ret == -EIO || ret == -EBADMSG)
+               if (ret == -EIO || mtd_is_eccerr(ret))
                        mtdswap_handle_write_error(d, eb);
                return ret;
        }
@@ -628,7 +628,7 @@ static int mtdswap_map_free_block(struct mtdswap_dev *d, unsigned int page,
                        TREE_COUNT(d, CLEAN)--;
 
                        ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_DIRTY);
-               } while (ret == -EIO || ret == -EBADMSG);
+               } while (ret == -EIO || mtd_is_eccerr(ret));
 
                if (ret)
                        return ret;
@@ -678,7 +678,7 @@ retry:
        ret = mtdswap_map_free_block(d, page, bp);
        eb = d->eb_data + (*bp / d->pages_per_eblk);
 
-       if (ret == -EIO || ret == -EBADMSG) {
+       if (ret == -EIO || mtd_is_eccerr(ret)) {
                d->curr_write = NULL;
                eb->active_count--;
                d->revmap[*bp] = PAGE_UNDEF;
@@ -690,7 +690,7 @@ retry:
 
        writepos = (loff_t)*bp << PAGE_SHIFT;
        ret =  mtd->write(mtd, writepos, PAGE_SIZE, &retlen, buf);
-       if (ret == -EIO || ret == -EBADMSG) {
+       if (ret == -EIO || mtd_is_eccerr(ret)) {
                d->curr_write_pos--;
                eb->active_count--;
                d->revmap[*bp] = PAGE_UNDEF;
@@ -738,7 +738,7 @@ static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock,
 retry:
        ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf);
 
-       if (ret < 0 && ret != -EUCLEAN) {
+       if (ret < 0 && !mtd_is_bitflip(ret)) {
                oldeb = d->eb_data + oldblock / d->pages_per_eblk;
                oldeb->flags |= EBLOCK_READERR;
 
@@ -931,7 +931,7 @@ static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d,
        struct mtd_oob_ops ops;
        int ret;
 
-       ops.mode = MTD_OOB_AUTO;
+       ops.mode = MTD_OPS_AUTO_OOB;
        ops.len = mtd->writesize;
        ops.ooblen = mtd->ecclayout->oobavail;
        ops.ooboffs = 0;
@@ -1016,7 +1016,7 @@ static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background)
 
        if (ret == 0)
                mtdswap_rb_add(d, eb, MTDSWAP_CLEAN);
-       else if (ret != -EIO && ret != -EBADMSG)
+       else if (ret != -EIO && !mtd_is_eccerr(ret))
                mtdswap_rb_add(d, eb, MTDSWAP_DIRTY);
 
        return 0;
@@ -1164,7 +1164,7 @@ retry:
        ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, buf);
 
        d->mtd_read_count++;
-       if (ret == -EUCLEAN) {
+       if (mtd_is_bitflip(ret)) {
                eb->flags |= EBLOCK_BITFLIP;
                mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP);
                ret = 0;
@@ -1374,11 +1374,10 @@ static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks,
                goto revmap_fail;
 
        eblk_bytes = sizeof(struct swap_eb)*d->eblks;
-       d->eb_data = vmalloc(eblk_bytes);
+       d->eb_data = vzalloc(eblk_bytes);
        if (!d->eb_data)
                goto eb_data_fail;
 
-       memset(d->eb_data, 0, eblk_bytes);
        for (i = 0; i < pages; i++)
                d->page_data[i] = BLOCK_UNDEF;
 
index dbfa0f7fb4643bb62d9405c9871170429d064012..cce7b70824c35076957664218e09c9a4e196a41c 100644 (file)
@@ -83,16 +83,9 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR
           scratch register here to enable this feature. On Intel Moorestown
           boards, the scratch register is at 0xFF108018.
 
-config MTD_NAND_EDB7312
-       tristate "Support for Cirrus Logic EBD7312 evaluation board"
-       depends on ARCH_EDB7312
-       help
-         This enables the driver for the Cirrus Logic EBD7312 evaluation
-         board to access the onboard NAND Flash.
-
 config MTD_NAND_H1900
        tristate "iPAQ H1900 flash"
-       depends on ARCH_PXA
+       depends on ARCH_PXA && BROKEN
        help
          This enables the driver for the iPAQ h1900 flash.
 
@@ -116,10 +109,11 @@ config MTD_NAND_AMS_DELTA
          Support for NAND flash on Amstrad E3 (Delta).
 
 config MTD_NAND_OMAP2
-       tristate "NAND Flash device on OMAP2 and OMAP3"
-       depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3)
+       tristate "NAND Flash device on OMAP2, OMAP3 and OMAP4"
+       depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4)
        help
-          Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
+          Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4
+         platforms.
 
 config MTD_NAND_IDS
        tristate
@@ -423,6 +417,19 @@ config MTD_NAND_NANDSIM
          The simulator may simulate various NAND flash chips for the
          MTD nand layer.
 
+config MTD_NAND_GPMI_NAND
+        bool "GPMI NAND Flash Controller driver"
+        depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28)
+       select MTD_PARTITIONS
+       select MTD_CMDLINE_PARTS
+        help
+        Enables NAND Flash support for IMX23 or IMX28.
+        The GPMI controller is very powerful, with the help of BCH
+        module, it can do the hardware ECC. The GPMI supports several
+        NAND flashs at the same time. The GPMI may conflicts with other
+        block, such as SD card. So pay attention to it when you enable
+        the GPMI.
+
 config MTD_NAND_PLATFORM
        tristate "Support for generic platform NAND driver"
        help
index 5745d831168e4e6f581deb1e12bb3a5b77f456fd..618f4ba23699ecbd5115e17f720164fcdaa29c7a 100644 (file)
@@ -13,7 +13,6 @@ obj-$(CONFIG_MTD_NAND_SPIA)           += spia.o
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)       += ams-delta.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)                += autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)          += denali.o
-obj-$(CONFIG_MTD_NAND_EDB7312)         += edb7312.o
 obj-$(CONFIG_MTD_NAND_AU1550)          += au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)           += bf5xx_nand.o
 obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB)  += ppchameleonevb.o
@@ -49,5 +48,6 @@ obj-$(CONFIG_MTD_NAND_BCM_UMI)                += bcm_umi_nand.o nand_bcm_umi.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)     += mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)           += r852.o
 obj-$(CONFIG_MTD_NAND_JZ4740)          += jz4740_nand.o
+obj-$(CONFIG_MTD_NAND_GPMI_NAND)       += gpmi-nand/
 
 nand-objs := nand_base.o nand_bbt.o
index 55da20ccc7a8996f0d80be785b91452e35dd8225..23e5d77c39fcaf998f81125e51d22ccf1ce9b2d3 100644 (file)
@@ -161,37 +161,6 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
                 !!host->board->rdy_pin_active_low;
 }
 
-/*
- * Minimal-overhead PIO for data access.
- */
-static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
-{
-       struct nand_chip        *nand_chip = mtd->priv;
-
-       __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
-}
-
-static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
-{
-       struct nand_chip        *nand_chip = mtd->priv;
-
-       __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
-}
-
-static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
-{
-       struct nand_chip        *nand_chip = mtd->priv;
-
-       __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
-}
-
-static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
-{
-       struct nand_chip        *nand_chip = mtd->priv;
-
-       __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
-}
-
 static void dma_complete_func(void *completion)
 {
        complete(completion);
@@ -266,33 +235,27 @@ err_buf:
 static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
        struct nand_chip *chip = mtd->priv;
-       struct atmel_nand_host *host = chip->priv;
 
        if (use_dma && len > mtd->oobsize)
                /* only use DMA for bigger than oob size: better performances */
                if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
                        return;
 
-       if (host->board->bus_width_16)
-               atmel_read_buf16(mtd, buf, len);
-       else
-               atmel_read_buf8(mtd, buf, len);
+       /* if no DMA operation possible, use PIO */
+       memcpy_fromio(buf, chip->IO_ADDR_R, len);
 }
 
 static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
        struct nand_chip *chip = mtd->priv;
-       struct atmel_nand_host *host = chip->priv;
 
        if (use_dma && len > mtd->oobsize)
                /* only use DMA for bigger than oob size: better performances */
                if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
                        return;
 
-       if (host->board->bus_width_16)
-               atmel_write_buf16(mtd, buf, len);
-       else
-               atmel_write_buf8(mtd, buf, len);
+       /* if no DMA operation possible, use PIO */
+       memcpy_toio(chip->IO_ADDR_W, buf, len);
 }
 
 /*
@@ -481,10 +444,6 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
        }
 }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
-
 /*
  * Probe for the NAND device.
  */
@@ -496,8 +455,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        struct resource *regs;
        struct resource *mem;
        int res;
-       struct mtd_partition *partitions = NULL;
-       int num_partitions = 0;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
@@ -583,7 +540,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 
        if (on_flash_bbt) {
                printk(KERN_INFO "atmel_nand: Use On Flash BBT\n");
-               nand_chip->options |= NAND_USE_FLASH_BBT;
+               nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
        }
 
        if (!cpu_has_dma())
@@ -594,7 +551,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 
                dma_cap_zero(mask);
                dma_cap_set(DMA_MEMCPY, mask);
-               host->dma_chan = dma_request_channel(mask, 0, NULL);
+               host->dma_chan = dma_request_channel(mask, NULL, NULL);
                if (!host->dma_chan) {
                        dev_err(host->dev, "Failed to request DMA channel\n");
                        use_dma = 0;
@@ -655,27 +612,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                goto err_scan_tail;
        }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
        mtd->name = "atmel_nand";
-       num_partitions = parse_mtd_partitions(mtd, part_probes,
-                                             &partitions, 0);
-#endif
-       if (num_partitions <= 0 && host->board->partition_info)
-               partitions = host->board->partition_info(mtd->size,
-                                                        &num_partitions);
-
-       if ((!partitions) || (num_partitions == 0)) {
-               printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");
-               res = -ENXIO;
-               goto err_no_partitions;
-       }
-
-       res = mtd_device_register(mtd, partitions, num_partitions);
+       res = mtd_device_parse_register(mtd, NULL, 0,
+                       host->board->parts, host->board->num_parts);
        if (!res)
                return res;
 
-err_no_partitions:
-       nand_release(mtd);
 err_scan_tail:
 err_scan_ident:
 err_no_card:
index fa5736b9286c2060bd6af631f704dd146b192566..7dd3700f2303097f14747098031a41d66acc130a 100644 (file)
@@ -52,7 +52,7 @@ static const struct mtd_partition partition_info[] = {
  * au_read_byte -  read one byte from the chip
  * @mtd:       MTD device structure
  *
- *  read function for 8bit buswith
+ * read function for 8bit buswidth
  */
 static u_char au_read_byte(struct mtd_info *mtd)
 {
@@ -67,7 +67,7 @@ static u_char au_read_byte(struct mtd_info *mtd)
  * @mtd:       MTD device structure
  * @byte:      pointer to data byte to write
  *
- *  write function for 8it buswith
+ * write function for 8it buswidth
  */
 static void au_write_byte(struct mtd_info *mtd, u_char byte)
 {
@@ -77,11 +77,10 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
 }
 
 /**
- * au_read_byte16 -  read one byte endianess aware from the chip
+ * au_read_byte16 -  read one byte endianness aware from the chip
  * @mtd:       MTD device structure
  *
- *  read function for 16bit buswith with
- * endianess conversion
+ * read function for 16bit buswidth with endianness conversion
  */
 static u_char au_read_byte16(struct mtd_info *mtd)
 {
@@ -92,12 +91,11 @@ static u_char au_read_byte16(struct mtd_info *mtd)
 }
 
 /**
- * au_write_byte16 -  write one byte endianess aware to the chip
+ * au_write_byte16 -  write one byte endianness aware to the chip
  * @mtd:       MTD device structure
  * @byte:      pointer to data byte to write
  *
- *  write function for 16bit buswith with
- * endianess conversion
+ * write function for 16bit buswidth with endianness conversion
  */
 static void au_write_byte16(struct mtd_info *mtd, u_char byte)
 {
@@ -110,8 +108,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
  * au_read_word -  read one word from the chip
  * @mtd:       MTD device structure
  *
- *  read function for 16bit buswith without
- * endianess conversion
+ * read function for 16bit buswidth without endianness conversion
  */
 static u16 au_read_word(struct mtd_info *mtd)
 {
@@ -127,7 +124,7 @@ static u16 au_read_word(struct mtd_info *mtd)
  * @buf:       data buffer
  * @len:       number of bytes to write
  *
- *  write function for 8bit buswith
+ * write function for 8bit buswidth
  */
 static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -146,7 +143,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
  * @buf:       buffer to store date
  * @len:       number of bytes to read
  *
- *  read function for 8bit buswith
+ * read function for 8bit buswidth
  */
 static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
@@ -165,7 +162,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
  * @buf:       buffer containing the data to compare
  * @len:       number of bytes to compare
  *
- *  verify function for 8bit buswith
+ * verify function for 8bit buswidth
  */
 static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -187,7 +184,7 @@ static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
  * @buf:       data buffer
  * @len:       number of bytes to write
  *
- *  write function for 16bit buswith
+ * write function for 16bit buswidth
  */
 static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -209,7 +206,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
  * @buf:       buffer to store date
  * @len:       number of bytes to read
  *
- *  read function for 16bit buswith
+ * read function for 16bit buswidth
  */
 static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
 {
@@ -230,7 +227,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
  * @buf:       buffer containing the data to compare
  * @len:       number of bytes to compare
  *
- *  verify function for 16bit buswith
+ * verify function for 16bit buswidth
  */
 static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 {
index eddc9a2249859efe157dac13f8042da3afaf26e6..2e42ec2e8ff48a285b939e7510ea91d22dd6035f 100644 (file)
@@ -172,9 +172,9 @@ static int __init autcpu12_init(void)
 
        /* Enable the following for a flash based bad block table */
        /*
-          this->options = NAND_USE_FLASH_BBT;
+          this->bbt_options = NAND_BBT_USE_FLASH;
         */
-       this->options = NAND_USE_FLASH_BBT;
+       this->bbt_options = NAND_BBT_USE_FLASH;
 
        /* Scan to find existence of the device */
        if (nand_scan(autcpu12_mtd, 1)) {
index 8c569e454dc5b52248fa98017e0d1071f6700f64..46b58d67284726fe2cee86852f9fe4640679a8a6 100644 (file)
@@ -52,8 +52,6 @@
 static const __devinitconst char gBanner[] = KERN_INFO \
        "BCM UMI MTD NAND Driver: 1.00\n";
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-
 #if NAND_ECC_BCH
 static uint8_t scan_ff_pattern[] = { 0xff };
 
@@ -376,16 +374,18 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       if (!r)
-               return -ENXIO;
+       if (!r) {
+               err = -ENXIO;
+               goto out_free;
+       }
 
        /* map physical address */
        bcm_umi_io_base = ioremap(r->start, resource_size(r));
 
        if (!bcm_umi_io_base) {
                printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n");
-               kfree(board_mtd);
-               return -EIO;
+               err = -EIO;
+               goto out_free;
        }
 
        /* Get pointer to private data */
@@ -401,9 +401,8 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
        /* Initialize the NAND hardware.  */
        if (bcm_umi_nand_inithw() < 0) {
                printk(KERN_ERR "BCM UMI NAND chip could not be initialized\n");
-               iounmap(bcm_umi_io_base);
-               kfree(board_mtd);
-               return -EIO;
+               err = -EIO;
+               goto out_unmap;
        }
 
        /* Set address of NAND IO lines */
@@ -436,7 +435,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
 #if USE_DMA
        err = nand_dma_init();
        if (err != 0)
-               return err;
+               goto out_unmap;
 #endif
 
        /* Figure out the size of the device that we have.
@@ -447,9 +446,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
        err = nand_scan_ident(board_mtd, 1, NULL);
        if (err) {
                printk(KERN_ERR "nand_scan failed: %d\n", err);
-               iounmap(bcm_umi_io_base);
-               kfree(board_mtd);
-               return err;
+               goto out_unmap;
        }
 
        /* Now that we know the nand size, we can setup the ECC layout */
@@ -468,13 +465,14 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
                {
                        printk(KERN_ERR "NAND - Unrecognized pagesize: %d\n",
                                         board_mtd->writesize);
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto out_unmap;
                }
        }
 
 #if NAND_ECC_BCH
        if (board_mtd->writesize > 512) {
-               if (this->options & NAND_USE_FLASH_BBT)
+               if (this->bbt_options & NAND_BBT_USE_FLASH)
                        largepage_bbt.options = NAND_BBT_SCAN2NDPAGE;
                this->badblock_pattern = &largepage_bbt;
        }
@@ -485,33 +483,20 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
        err = nand_scan_tail(board_mtd);
        if (err) {
                printk(KERN_ERR "nand_scan failed: %d\n", err);
-               iounmap(bcm_umi_io_base);
-               kfree(board_mtd);
-               return err;
+               goto out_unmap;
        }
 
        /* Register the partitions */
-       {
-               int nr_partitions;
-               struct mtd_partition *partition_info;
-
-               board_mtd->name = "bcm_umi-nand";
-               nr_partitions =
-                   parse_mtd_partitions(board_mtd, part_probes,
-                                        &partition_info, 0);
-
-               if (nr_partitions <= 0) {
-                       printk(KERN_ERR "BCM UMI NAND: Too few partitions - %d\n",
-                              nr_partitions);
-                       iounmap(bcm_umi_io_base);
-                       kfree(board_mtd);
-                       return -EIO;
-               }
-               mtd_device_register(board_mtd, partition_info, nr_partitions);
-       }
+       board_mtd->name = "bcm_umi-nand";
+       mtd_device_parse_register(board_mtd, NULL, 0, NULL, 0);
 
        /* Return happy */
        return 0;
+out_unmap:
+       iounmap(bcm_umi_io_base);
+out_free:
+       kfree(board_mtd);
+       return err;
 }
 
 static int bcm_umi_nand_remove(struct platform_device *pdev)
index 7c8df837d3b88ab1d73c08e8061eb42c94e38ab3..72d3f23490c58a548c962b1771c44f3781560da9 100644 (file)
@@ -58,7 +58,6 @@
 
 struct cafe_priv {
        struct nand_chip nand;
-       struct mtd_partition *parts;
        struct pci_dev *pdev;
        void __iomem *mmio;
        struct rs_control *rs;
@@ -372,7 +371,7 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
        return 1;
 }
 /**
- * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read
  * @mtd:       mtd info structure
  * @chip:      nand chip info structure
  * @buf:       buffer to store read data
@@ -631,8 +630,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
        struct cafe_priv *cafe;
        uint32_t ctrl;
        int err = 0;
-       struct mtd_partition *parts;
-       int nr_parts;
 
        /* Very old versions shared the same PCI ident for all three
           functions on the chip. Verify the class too... */
@@ -687,7 +684,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
        cafe->nand.chip_delay = 0;
 
        /* Enable the following for a flash based bad block table */
-       cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS;
+       cafe->nand.bbt_options = NAND_BBT_USE_FLASH;
+       cafe->nand.options = NAND_NO_AUTOINCR | NAND_OWN_BUFFERS;
 
        if (skipbbt) {
                cafe->nand.options |= NAND_SKIP_BBTSCAN;
@@ -800,18 +798,9 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, mtd);
 
-       /* We register the whole device first, separate from the partitions */
-       mtd_device_register(mtd, NULL, 0);
-
-#ifdef CONFIG_MTD_CMDLINE_PARTS
        mtd->name = "cafe_nand";
-#endif
-       nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
-       if (nr_parts > 0) {
-               cafe->parts = parts;
-               dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts);
-               mtd_device_register(mtd, parts, nr_parts);
-       }
+       mtd_device_parse_register(mtd, part_probes, 0, NULL, 0);
+
        goto out;
 
  out_irq:
index be33b0f4634dcc754fe3713c169735d1f39f6c1d..737ef9a04fdbf35dc03253e49d26281ade9fff95 100644 (file)
@@ -51,8 +51,6 @@ static struct mtd_partition partition_info[] = {
 };
 #define NUM_PARTITIONS (ARRAY_SIZE(partition_info))
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-
 static u_char cmx270_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
@@ -152,9 +150,6 @@ static int cmx270_device_ready(struct mtd_info *mtd)
 static int __init cmx270_init(void)
 {
        struct nand_chip *this;
-       const char *part_type;
-       struct mtd_partition *mtd_parts;
-       int mtd_parts_nb = 0;
        int ret;
 
        if (!(machine_is_armcore() && cpu_is_pxa27x()))
@@ -223,23 +218,9 @@ static int __init cmx270_init(void)
                goto err_scan;
        }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-       mtd_parts_nb = parse_mtd_partitions(cmx270_nand_mtd, part_probes,
-                                           &mtd_parts, 0);
-       if (mtd_parts_nb > 0)
-               part_type = "command line";
-       else
-               mtd_parts_nb = 0;
-#endif
-       if (!mtd_parts_nb) {
-               mtd_parts = partition_info;
-               mtd_parts_nb = NUM_PARTITIONS;
-               part_type = "static";
-       }
-
        /* Register the partitions */
-       pr_notice("Using %s partition definition\n", part_type);
-       ret = mtd_device_register(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
+       ret = mtd_device_parse_register(cmx270_nand_mtd, NULL, 0,
+                                       partition_info, NUM_PARTITIONS);
        if (ret)
                goto err_scan;
 
index f59ad1f2d5dbe7e23fa10a7762332ff2ee44e3cb..414afa7935637522709f6273f2df9930a1170a6a 100644 (file)
@@ -239,7 +239,8 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
        this->ecc.correct  = nand_correct_data;
 
        /* Enable the following for a flash based bad block table */
-       this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
+       this->bbt_options = NAND_BBT_USE_FLASH;
+       this->options = NAND_NO_AUTOINCR;
 
        /* Scan to find existence of the device */
        if (nand_scan(new_mtd, 1)) {
@@ -277,15 +278,11 @@ static int is_geode(void)
        return 0;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 static int __init cs553x_init(void)
 {
        int err = -ENXIO;
        int i;
        uint64_t val;
-       int mtd_parts_nb = 0;
-       struct mtd_partition *mtd_parts = NULL;
 
        /* If the CPU isn't a Geode GX or LX, abort */
        if (!is_geode())
@@ -315,13 +312,9 @@ static int __init cs553x_init(void)
           do mtdconcat etc. if we want to. */
        for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
                if (cs553x_mtd[i]) {
-
                        /* If any devices registered, return success. Else the last error. */
-                       mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0);
-                       if (mtd_parts_nb > 0)
-                               printk(KERN_NOTICE "Using command line partition definition\n");
-                       mtd_device_register(cs553x_mtd[i], mtd_parts,
-                                           mtd_parts_nb);
+                       mtd_device_parse_register(cs553x_mtd[i], NULL, 0,
+                                                 NULL, 0);
                        err = 0;
                }
        }
index 1f34951ae1a7426f0344a7327c56a5b1105c7bc8..c153e1f77f90d0e58dc6d892f2395a71e500b7ef 100644 (file)
@@ -57,7 +57,6 @@ struct davinci_nand_info {
 
        struct device           *dev;
        struct clk              *clk;
-       bool                    partitioned;
 
        bool                    is_readmode;
 
@@ -530,8 +529,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        int                             ret;
        uint32_t                        val;
        nand_ecc_modes_t                ecc_mode;
-       struct mtd_partition            *mtd_parts = NULL;
-       int                             mtd_parts_nb = 0;
 
        /* insist on board-specific configuration */
        if (!pdata)
@@ -581,7 +578,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        info->chip.chip_delay   = 0;
        info->chip.select_chip  = nand_davinci_select_chip;
 
-       /* options such as NAND_USE_FLASH_BBT or 16-bit widths */
+       /* options such as NAND_BBT_USE_FLASH */
+       info->chip.bbt_options  = pdata->bbt_options;
+       /* options such as 16-bit widths */
        info->chip.options      = pdata->options;
        info->chip.bbt_td       = pdata->bbt_td;
        info->chip.bbt_md       = pdata->bbt_md;
@@ -751,33 +750,8 @@ syndrome_done:
        if (ret < 0)
                goto err_scan;
 
-       if (mtd_has_cmdlinepart()) {
-               static const char *probes[] __initconst = {
-                       "cmdlinepart", NULL
-               };
-
-               mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes,
-                                                   &mtd_parts, 0);
-       }
-
-       if (mtd_parts_nb <= 0) {
-               mtd_parts = pdata->parts;
-               mtd_parts_nb = pdata->nr_parts;
-       }
-
-       /* Register any partitions */
-       if (mtd_parts_nb > 0) {
-               ret = mtd_device_register(&info->mtd, mtd_parts,
-                                         mtd_parts_nb);
-               if (ret == 0)
-                       info->partitioned = true;
-       }
-
-       /* If there's no partition info, just package the whole chip
-        * as a single MTD device.
-        */
-       if (!info->partitioned)
-               ret = mtd_device_register(&info->mtd, NULL, 0) ? -ENODEV : 0;
+       ret = mtd_device_parse_register(&info->mtd, NULL, 0,
+                       pdata->parts, pdata->nr_parts);
 
        if (ret < 0)
                goto err_scan;
@@ -816,9 +790,6 @@ err_nomem:
 static int __exit nand_davinci_remove(struct platform_device *pdev)
 {
        struct davinci_nand_info *info = platform_get_drvdata(pdev);
-       int status;
-
-       status = mtd_device_unregister(&info->mtd);
 
        spin_lock_irq(&davinci_nand_lock);
        if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
index d5276218945fe296cb1c1b8c29cb8f21929dfb42..3984d488f9abbf5a3d6ed77fd49e2c4b7dc79381 100644 (file)
@@ -1346,6 +1346,7 @@ static void denali_hw_init(struct denali_nand_info *denali)
         * */
        denali->bbtskipbytes = ioread32(denali->flash_reg +
                                                SPARE_AREA_SKIP_BYTES);
+       detect_max_banks(denali);
        denali_nand_reset(denali);
        iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
        iowrite32(CHIP_EN_DONT_CARE__FLAG,
@@ -1356,7 +1357,6 @@ static void denali_hw_init(struct denali_nand_info *denali)
        /* Should set value for these registers when init */
        iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES);
        iowrite32(1, denali->flash_reg + ECC_ENABLE);
-       detect_max_banks(denali);
        denali_nand_timing_set(denali);
        denali_irq_init(denali);
 }
@@ -1577,7 +1577,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        denali->nand.bbt_md = &bbt_mirror_descr;
 
        /* skip the scan for now until we have OOB read and write support */
-       denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
+       denali->nand.bbt_options |= NAND_BBT_USE_FLASH;
+       denali->nand.options |= NAND_SKIP_BBTSCAN;
        denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
 
        /* Denali Controller only support 15bit and 8bit ECC in MRST,
@@ -1676,7 +1677,6 @@ static void denali_pci_remove(struct pci_dev *dev)
        struct denali_nand_info *denali = pci_get_drvdata(dev);
 
        nand_release(&denali->mtd);
-       mtd_device_unregister(&denali->mtd);
 
        denali_irq_cleanup(dev->irq, denali);
 
index e1b84cb90f0db6f4cd0a206f3080f3f80d5c078d..5780dbab611360d546c0770fb378060a223edda8 100644 (file)
@@ -133,7 +133,7 @@ static struct rs_control *rs_decoder;
 
 /*
  * The HW decoder in the DoC ASIC's provides us a error syndrome,
- * which we must convert to a standard syndrom usable by the generic
+ * which we must convert to a standard syndrome usable by the generic
  * Reed-Solomon library code.
  *
  * Fabrice Bellard figured this out in the old docecc code. I added
@@ -154,7 +154,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
        ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2);
        parity = ecc[1];
 
-       /* Initialize the syndrom buffer */
+       /* Initialize the syndrome buffer */
        for (i = 0; i < NROOTS; i++)
                s[i] = ds[0];
        /*
@@ -1032,7 +1032,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
                WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
        else
                WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
-       if (no_ecc_failures && (ret == -EBADMSG)) {
+       if (no_ecc_failures && mtd_is_eccerr(ret)) {
                printk(KERN_ERR "suppressing ECC failure\n");
                ret = 0;
        }
@@ -1653,7 +1653,7 @@ static int __init doc_probe(unsigned long physadr)
        nand->ecc.mode          = NAND_ECC_HW_SYNDROME;
        nand->ecc.size          = 512;
        nand->ecc.bytes         = 6;
-       nand->options           = NAND_USE_FLASH_BBT;
+       nand->bbt_options       = NAND_BBT_USE_FLASH;
 
        doc->physadr            = physadr;
        doc->virtadr            = virtadr;
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
deleted file mode 100644 (file)
index 8400d0f..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *  drivers/mtd/nand/edb7312.c
- *
- *  Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
- *
- *  Derived from drivers/mtd/nand/autcpu12.c
- *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.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.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   CLEP7312 board which utilizes the Toshiba TC58V64AFT part. This is
- *   a 64Mibit (8MiB x 8 bits) NAND flash device.
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <mach/hardware.h>     /* for CLPS7111_VIRT_BASE */
-#include <asm/sizes.h>
-#include <asm/hardware/clps7111.h>
-
-/*
- * MTD structure for EDB7312 board
- */
-static struct mtd_info *ep7312_mtd = NULL;
-
-/*
- * Values specific to the EDB7312 board (used with EP7312 processor)
- */
-#define EP7312_FIO_PBASE 0x10000000    /* Phys address of flash */
-#define EP7312_PXDR    0x0001  /*
-                                * IO offset to Port B data register
-                                * where the CLE, ALE and NCE pins
-                                * are wired to.
-                                */
-#define EP7312_PXDDR   0x0041  /*
-                                * IO offset to Port B data direction
-                                * register so we can control the IO
-                                * lines.
-                                */
-
-/*
- * Module stuff
- */
-
-static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
-static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR;
-static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR;
-
-/*
- * Define static partitions for flash device
- */
-static struct mtd_partition partition_info[] = {
-       {.name = "EP7312 Nand Flash",
-        .offset = 0,
-        .size = 8 * 1024 * 1024}
-};
-
-#define NUM_PARTITIONS 1
-
-/*
- *     hardware specific access to control-lines
- *
- *     NAND_NCE: bit 0 -> bit 6 (bit 7 = 1)
- *     NAND_CLE: bit 1 -> bit 4
- *     NAND_ALE: bit 2 -> bit 5
- */
-static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-       struct nand_chip *chip = mtd->priv;
-
-       if (ctrl & NAND_CTRL_CHANGE) {
-               unsigned char bits = 0x80;
-
-               bits |= (ctrl & (NAND_CLE | NAND_ALE)) << 3;
-               bits |= (ctrl & NAND_NCE) ? 0x00 : 0x40;
-
-               clps_writeb((clps_readb(ep7312_pxdr)  & 0xF0) | bits,
-                           ep7312_pxdr);
-       }
-       if (cmd != NAND_CMD_NONE)
-               writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- *     read device ready pin
- */
-static int ep7312_device_ready(struct mtd_info *mtd)
-{
-       return 1;
-}
-
-const char *part_probes[] = { "cmdlinepart", NULL };
-
-/*
- * Main initialization routine
- */
-static int __init ep7312_init(void)
-{
-       struct nand_chip *this;
-       const char *part_type = 0;
-       int mtd_parts_nb = 0;
-       struct mtd_partition *mtd_parts = 0;
-       void __iomem *ep7312_fio_base;
-
-       /* Allocate memory for MTD device structure and private data */
-       ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-       if (!ep7312_mtd) {
-               printk("Unable to allocate EDB7312 NAND MTD device structure.\n");
-               return -ENOMEM;
-       }
-
-       /* map physical address */
-       ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K);
-       if (!ep7312_fio_base) {
-               printk("ioremap EDB7312 NAND flash failed\n");
-               kfree(ep7312_mtd);
-               return -EIO;
-       }
-
-       /* Get pointer to private data */
-       this = (struct nand_chip *)(&ep7312_mtd[1]);
-
-       /* Initialize structures */
-       memset(ep7312_mtd, 0, sizeof(struct mtd_info));
-       memset(this, 0, sizeof(struct nand_chip));
-
-       /* Link the private data with the MTD structure */
-       ep7312_mtd->priv = this;
-       ep7312_mtd->owner = THIS_MODULE;
-
-       /*
-        * Set GPIO Port B control register so that the pins are configured
-        * to be outputs for controlling the NAND flash.
-        */
-       clps_writeb(0xf0, ep7312_pxddr);
-
-       /* insert callbacks */
-       this->IO_ADDR_R = ep7312_fio_base;
-       this->IO_ADDR_W = ep7312_fio_base;
-       this->cmd_ctrl = ep7312_hwcontrol;
-       this->dev_ready = ep7312_device_ready;
-       /* 15 us command delay time */
-       this->chip_delay = 15;
-
-       /* Scan to find existence of the device */
-       if (nand_scan(ep7312_mtd, 1)) {
-               iounmap((void *)ep7312_fio_base);
-               kfree(ep7312_mtd);
-               return -ENXIO;
-       }
-       ep7312_mtd->name = "edb7312-nand";
-       mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0);
-       if (mtd_parts_nb > 0)
-               part_type = "command line";
-       else
-               mtd_parts_nb = 0;
-       if (mtd_parts_nb == 0) {
-               mtd_parts = partition_info;
-               mtd_parts_nb = NUM_PARTITIONS;
-               part_type = "static";
-       }
-
-       /* Register the partitions */
-       printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-       mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb);
-
-       /* Return happy */
-       return 0;
-}
-
-module_init(ep7312_init);
-
-/*
- * Clean up routine
- */
-static void __exit ep7312_cleanup(void)
-{
-       struct nand_chip *this = (struct nand_chip *)&ep7312_mtd[1];
-
-       /* Release resources, unregister device */
-       nand_release(ap7312_mtd);
-
-       /* Release io resource */
-       iounmap(this->IO_ADDR_R);
-
-       /* Free the MTD device structure */
-       kfree(ep7312_mtd);
-}
-
-module_exit(ep7312_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
-MODULE_DESCRIPTION("MTD map driver for Cogent EDB7312 board");
index 33d8aad8bba5a47b2c0135acf4132454bab12eea..eedd8ee2c9ac8b83059edf9cf5856a12e4a53e48 100644 (file)
@@ -75,7 +75,6 @@ struct fsl_elbc_fcm_ctrl {
        unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
        unsigned int oob;        /* Non zero if operating on OOB data     */
        unsigned int counter;    /* counter for the initializations       */
-       char *oob_poi;           /* Place to write ECC after read back    */
 };
 
 /* These map to the positions used by the FCM hardware ECC generator */
@@ -244,6 +243,25 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
                return -EIO;
        }
 
+       if (chip->ecc.mode != NAND_ECC_HW)
+               return 0;
+
+       if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) {
+               uint32_t lteccr = in_be32(&lbc->lteccr);
+               /*
+                * if command was a full page read and the ELBC
+                * has the LTECCR register, then bits 12-15 (ppc order) of
+                * LTECCR indicates which 512 byte sub-pages had fixed errors.
+                * bits 28-31 are uncorrectable errors, marked elsewhere.
+                * for small page nand only 1 bit is used.
+                * if the ELBC doesn't have the lteccr register it reads 0
+                */
+               if (lteccr & 0x000F000F)
+                       out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */
+               if (lteccr & 0x000F0000)
+                       mtd->ecc_stats.corrected++;
+       }
+
        return 0;
 }
 
@@ -435,7 +453,6 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
        /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
        case NAND_CMD_PAGEPROG: {
-               int full_page;
                dev_vdbg(priv->dev,
                         "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
                         "writing %d bytes.\n", elbc_fcm_ctrl->index);
@@ -445,34 +462,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                 * write so the HW generates the ECC.
                 */
                if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
-                   elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
+                   elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize)
                        out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
-                       full_page = 0;
-               } else {
+               else
                        out_be32(&lbc->fbcr, 0);
-                       full_page = 1;
-               }
 
                fsl_elbc_run_command(mtd);
-
-               /* Read back the page in order to fill in the ECC for the
-                * caller.  Is this really needed?
-                */
-               if (full_page && elbc_fcm_ctrl->oob_poi) {
-                       out_be32(&lbc->fbcr, 3);
-                       set_addr(mtd, 6, page_addr, 1);
-
-                       elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
-
-                       fsl_elbc_do_read(chip, 1);
-                       fsl_elbc_run_command(mtd);
-
-                       memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
-                               &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
-                       elbc_fcm_ctrl->index += 3;
-               }
-
-               elbc_fcm_ctrl->oob_poi = NULL;
                return;
        }
 
@@ -752,13 +747,8 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
                                 struct nand_chip *chip,
                                 const uint8_t *buf)
 {
-       struct fsl_elbc_mtd *priv = chip->priv;
-       struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
-
        fsl_elbc_write_buf(mtd, buf, mtd->writesize);
        fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-       elbc_fcm_ctrl->oob_poi = chip->oob_poi;
 }
 
 static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
@@ -791,8 +781,8 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
        chip->bbt_md = &bbt_mirror_descr;
 
        /* set up nand options */
-       chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
-                       NAND_USE_FLASH_BBT;
+       chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;
+       chip->bbt_options = NAND_BBT_USE_FLASH;
 
        chip->controller = &elbc_fcm_ctrl->controller;
        chip->priv = priv;
@@ -829,7 +819,6 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 
        elbc_fcm_ctrl->chips[priv->bank] = NULL;
        kfree(priv);
-       kfree(elbc_fcm_ctrl);
        return 0;
 }
 
@@ -842,13 +831,14 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
        struct resource res;
        struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
        static const char *part_probe_types[]
-               = { "cmdlinepart", "RedBoot", NULL };
-       struct mtd_partition *parts;
+               = { "cmdlinepart", "RedBoot", "ofpart", NULL };
        int ret;
        int bank;
        struct device *dev;
        struct device_node *node = pdev->dev.of_node;
+       struct mtd_part_parser_data ppdata;
 
+       ppdata.of_node = pdev->dev.of_node;
        if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
                return -ENODEV;
        lbc = fsl_lbc_ctrl_dev->regs;
@@ -934,17 +924,8 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 
        /* First look for RedBoot table or partitions on the command
         * line, these take precedence over device tree information */
-       ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0);
-       if (ret < 0)
-               goto err;
-
-       if (ret == 0) {
-               ret = of_mtd_parse_partitions(priv->dev, node, &parts);
-               if (ret < 0)
-                       goto err;
-       }
-
-       mtd_device_register(&priv->mtd, parts, ret);
+       mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
+                                 NULL, 0);
 
        printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
               (unsigned long long)res.start, priv->bank);
index 23752fd5bc590d40e7ac5fb15ad93af05d9e6882..b4f3cc9f32fbe5614ad8d1a0a1cbe905ee01d3f5 100644 (file)
@@ -158,7 +158,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 {
        int ret;
        struct device_node *flash_np;
-       static const char *part_types[] = { "cmdlinepart", NULL, };
+       struct mtd_part_parser_data ppdata;
 
        fun->chip.IO_ADDR_R = fun->io_base;
        fun->chip.IO_ADDR_W = fun->io_base;
@@ -192,18 +192,12 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
        if (ret)
                goto err;
 
-       ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
-
-#ifdef CONFIG_MTD_OF_PARTS
-       if (ret == 0) {
-               ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts);
-               if (ret < 0)
-                       goto err;
-       }
-#endif
-       ret = mtd_device_register(&fun->mtd, fun->parts, ret);
+       ppdata.of_node = flash_np;
+       ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0);
 err:
        of_node_put(flash_np);
+       if (ret)
+               kfree(fun->mtd.name);
        return ret;
 }
 
index e9b275ac381ce89fd53f6d5fbb1895d205ce2462..e53b76064133fc52bded214fb57a94696abcb891 100644 (file)
@@ -146,7 +146,7 @@ static struct mtd_partition partition_info_16KB_blk[] = {
        {
                .name = "Root File System",
                .offset = 0x460000,
-               .size = 0,
+               .size = MTDPART_SIZ_FULL,
        },
 };
 
@@ -173,13 +173,10 @@ static struct mtd_partition partition_info_128KB_blk[] = {
        {
                .name = "Root File System",
                .offset = 0x800000,
-               .size = 0,
+               .size = MTDPART_SIZ_FULL,
        },
 };
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /**
  * struct fsmc_nand_data - structure for FSMC NAND device state
@@ -187,8 +184,6 @@ const char *part_probes[] = { "cmdlinepart", NULL };
  * @pid:               Part ID on the AMBA PrimeCell format
  * @mtd:               MTD info for a NAND flash.
  * @nand:              Chip related info for a NAND flash.
- * @partitions:                Partition info for a NAND Flash.
- * @nr_partitions:     Total number of partition of a NAND flash.
  *
  * @ecc_place:         ECC placing locations in oobfree type format.
  * @bank:              Bank number for probed device.
@@ -203,8 +198,6 @@ struct fsmc_nand_data {
        u32                     pid;
        struct mtd_info         mtd;
        struct nand_chip        nand;
-       struct mtd_partition    *partitions;
-       unsigned int            nr_partitions;
 
        struct fsmc_eccplace    *ecc_place;
        unsigned int            bank;
@@ -716,65 +709,17 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
         * platform data,
         * default partition information present in driver.
         */
-#ifdef CONFIG_MTD_CMDLINE_PARTS
        /*
-        * Check if partition info passed via command line
+        * Check for partition info passed
         */
        host->mtd.name = "nand";
-       host->nr_partitions = parse_mtd_partitions(&host->mtd, part_probes,
-                       &host->partitions, 0);
-       if (host->nr_partitions <= 0) {
-#endif
-               /*
-                * Check if partition info passed via command line
-                */
-               if (pdata->partitions) {
-                       host->partitions = pdata->partitions;
-                       host->nr_partitions = pdata->nr_partitions;
-               } else {
-                       struct mtd_partition *partition;
-                       int i;
-
-                       /* Select the default partitions info */
-                       switch (host->mtd.size) {
-                       case 0x01000000:
-                       case 0x02000000:
-                       case 0x04000000:
-                               host->partitions = partition_info_16KB_blk;
-                               host->nr_partitions =
-                                       sizeof(partition_info_16KB_blk) /
-                                       sizeof(struct mtd_partition);
-                               break;
-                       case 0x08000000:
-                       case 0x10000000:
-                       case 0x20000000:
-                       case 0x40000000:
-                               host->partitions = partition_info_128KB_blk;
-                               host->nr_partitions =
-                                       sizeof(partition_info_128KB_blk) /
-                                       sizeof(struct mtd_partition);
-                               break;
-                       default:
-                               ret = -ENXIO;
-                               pr_err("Unsupported NAND size\n");
-                               goto err_probe;
-                       }
-
-                       partition = host->partitions;
-                       for (i = 0; i < host->nr_partitions; i++, partition++) {
-                               if (partition->size == 0) {
-                                       partition->size = host->mtd.size -
-                                               partition->offset;
-                                       break;
-                               }
-                       }
-               }
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-       }
-#endif
-
-       ret = mtd_device_register(&host->mtd, host->partitions,
-                                 host->nr_partitions);
+       ret = mtd_device_parse_register(&host->mtd, NULL, 0,
+                       host->mtd.size <= 0x04000000 ?
+                               partition_info_16KB_blk :
+                               partition_info_128KB_blk,
+                       host->mtd.size <= 0x04000000 ?
+                               ARRAY_SIZE(partition_info_16KB_blk) :
+                               ARRAY_SIZE(partition_info_128KB_blk));
        if (ret)
                goto err_probe;
 
@@ -822,7 +767,7 @@ static int fsmc_nand_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        if (host) {
-               mtd_device_unregister(&host->mtd);
+               nand_release(&host->mtd);
                clk_disable(host->clk);
                clk_put(host->clk);
 
diff --git a/drivers/mtd/nand/gpmi-nand/Makefile b/drivers/mtd/nand/gpmi-nand/Makefile
new file mode 100644 (file)
index 0000000..3a46248
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi_nand.o
+gpmi_nand-objs += gpmi-nand.o
+gpmi_nand-objs += gpmi-lib.o
diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/gpmi-nand/bch-regs.h
new file mode 100644 (file)
index 0000000..4effb8c
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __GPMI_NAND_BCH_REGS_H
+#define __GPMI_NAND_BCH_REGS_H
+
+#define HW_BCH_CTRL                            0x00000000
+#define HW_BCH_CTRL_SET                                0x00000004
+#define HW_BCH_CTRL_CLR                                0x00000008
+#define HW_BCH_CTRL_TOG                                0x0000000c
+
+#define BM_BCH_CTRL_COMPLETE_IRQ_EN            (1 << 8)
+#define BM_BCH_CTRL_COMPLETE_IRQ               (1 << 0)
+
+#define HW_BCH_STATUS0                         0x00000010
+#define HW_BCH_MODE                            0x00000020
+#define HW_BCH_ENCODEPTR                       0x00000030
+#define HW_BCH_DATAPTR                         0x00000040
+#define HW_BCH_METAPTR                         0x00000050
+#define HW_BCH_LAYOUTSELECT                    0x00000070
+
+#define HW_BCH_FLASH0LAYOUT0                   0x00000080
+
+#define BP_BCH_FLASH0LAYOUT0_NBLOCKS           24
+#define BM_BCH_FLASH0LAYOUT0_NBLOCKS   (0xff << BP_BCH_FLASH0LAYOUT0_NBLOCKS)
+#define BF_BCH_FLASH0LAYOUT0_NBLOCKS(v)                \
+       (((v) << BP_BCH_FLASH0LAYOUT0_NBLOCKS) & BM_BCH_FLASH0LAYOUT0_NBLOCKS)
+
+#define BP_BCH_FLASH0LAYOUT0_META_SIZE         16
+#define BM_BCH_FLASH0LAYOUT0_META_SIZE (0xff << BP_BCH_FLASH0LAYOUT0_META_SIZE)
+#define BF_BCH_FLASH0LAYOUT0_META_SIZE(v)      \
+       (((v) << BP_BCH_FLASH0LAYOUT0_META_SIZE)\
+                                        & BM_BCH_FLASH0LAYOUT0_META_SIZE)
+
+#define BP_BCH_FLASH0LAYOUT0_ECC0              12
+#define BM_BCH_FLASH0LAYOUT0_ECC0      (0xf << BP_BCH_FLASH0LAYOUT0_ECC0)
+#define BF_BCH_FLASH0LAYOUT0_ECC0(v)           \
+       (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) & BM_BCH_FLASH0LAYOUT0_ECC0)
+
+#define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE                0
+#define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE                \
+                       (0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)
+#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v)     \
+       (((v) << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)\
+                                        & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE)
+
+#define HW_BCH_FLASH0LAYOUT1                   0x00000090
+
+#define BP_BCH_FLASH0LAYOUT1_PAGE_SIZE         16
+#define BM_BCH_FLASH0LAYOUT1_PAGE_SIZE         \
+                       (0xffff << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE)
+#define BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(v)      \
+       (((v) << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE) \
+                                        & BM_BCH_FLASH0LAYOUT1_PAGE_SIZE)
+
+#define BP_BCH_FLASH0LAYOUT1_ECCN              12
+#define BM_BCH_FLASH0LAYOUT1_ECCN      (0xf << BP_BCH_FLASH0LAYOUT1_ECCN)
+#define BF_BCH_FLASH0LAYOUT1_ECCN(v)           \
+       (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) & BM_BCH_FLASH0LAYOUT1_ECCN)
+
+#define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE                0
+#define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE                \
+                       (0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE)
+#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v)     \
+       (((v) << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
+                                        & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE)
+#endif
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
new file mode 100644 (file)
index 0000000..de4db76
--- /dev/null
@@ -0,0 +1,1057 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <linux/mtd/gpmi-nand.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <mach/mxs.h>
+
+#include "gpmi-nand.h"
+#include "gpmi-regs.h"
+#include "bch-regs.h"
+
+struct timing_threshod timing_default_threshold = {
+       .max_data_setup_cycles       = (BM_GPMI_TIMING0_DATA_SETUP >>
+                                               BP_GPMI_TIMING0_DATA_SETUP),
+       .internal_data_setup_in_ns   = 0,
+       .max_sample_delay_factor     = (BM_GPMI_CTRL1_RDN_DELAY >>
+                                               BP_GPMI_CTRL1_RDN_DELAY),
+       .max_dll_clock_period_in_ns  = 32,
+       .max_dll_delay_in_ns         = 16,
+};
+
+/*
+ * Clear the bit and poll it cleared.  This is usually called with
+ * a reset address and mask being either SFTRST(bit 31) or CLKGATE
+ * (bit 30).
+ */
+static int clear_poll_bit(void __iomem *addr, u32 mask)
+{
+       int timeout = 0x400;
+
+       /* clear the bit */
+       __mxs_clrl(mask, addr);
+
+       /*
+        * SFTRST needs 3 GPMI clocks to settle, the reference manual
+        * recommends to wait 1us.
+        */
+       udelay(1);
+
+       /* poll the bit becoming clear */
+       while ((readl(addr) & mask) && --timeout)
+               /* nothing */;
+
+       return !timeout;
+}
+
+#define MODULE_CLKGATE         (1 << 30)
+#define MODULE_SFTRST          (1 << 31)
+/*
+ * The current mxs_reset_block() will do two things:
+ *  [1] enable the module.
+ *  [2] reset the module.
+ *
+ * In most of the cases, it's ok. But there is a hardware bug in the BCH block.
+ * If you try to soft reset the BCH block, it becomes unusable until
+ * the next hard reset. This case occurs in the NAND boot mode. When the board
+ * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
+ * So If the driver tries to reset the BCH again, the BCH will not work anymore.
+ * You will see a DMA timeout in this case.
+ *
+ * To avoid this bug, just add a new parameter `just_enable` for
+ * the mxs_reset_block(), and rewrite it here.
+ */
+int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
+{
+       int ret;
+       int timeout = 0x400;
+
+       /* clear and poll SFTRST */
+       ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+       if (unlikely(ret))
+               goto error;
+
+       /* clear CLKGATE */
+       __mxs_clrl(MODULE_CLKGATE, reset_addr);
+
+       if (!just_enable) {
+               /* set SFTRST to reset the block */
+               __mxs_setl(MODULE_SFTRST, reset_addr);
+               udelay(1);
+
+               /* poll CLKGATE becoming set */
+               while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout)
+                       /* nothing */;
+               if (unlikely(!timeout))
+                       goto error;
+       }
+
+       /* clear and poll SFTRST */
+       ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+       if (unlikely(ret))
+               goto error;
+
+       /* clear and poll CLKGATE */
+       ret = clear_poll_bit(reset_addr, MODULE_CLKGATE);
+       if (unlikely(ret))
+               goto error;
+
+       return 0;
+
+error:
+       pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
+       return -ETIMEDOUT;
+}
+
+int gpmi_init(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+       int ret;
+
+       ret = clk_enable(r->clock);
+       if (ret)
+               goto err_out;
+       ret = gpmi_reset_block(r->gpmi_regs, false);
+       if (ret)
+               goto err_out;
+
+       /* Choose NAND mode. */
+       writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+       /* Set the IRQ polarity. */
+       writel(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY,
+                               r->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+       /* Disable Write-Protection. */
+       writel(BM_GPMI_CTRL1_DEV_RESET, r->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+       /* Select BCH ECC. */
+       writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+       clk_disable(r->clock);
+       return 0;
+err_out:
+       return ret;
+}
+
+/* This function is very useful. It is called only when the bug occur. */
+void gpmi_dump_info(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+       struct bch_geometry *geo = &this->bch_geometry;
+       u32 reg;
+       int i;
+
+       pr_err("Show GPMI registers :\n");
+       for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
+               reg = readl(r->gpmi_regs + i * 0x10);
+               pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+       }
+
+       /* start to print out the BCH info */
+       pr_err("BCH Geometry :\n");
+       pr_err("GF length              : %u\n", geo->gf_len);
+       pr_err("ECC Strength           : %u\n", geo->ecc_strength);
+       pr_err("Page Size in Bytes     : %u\n", geo->page_size);
+       pr_err("Metadata Size in Bytes : %u\n", geo->metadata_size);
+       pr_err("ECC Chunk Size in Bytes: %u\n", geo->ecc_chunk_size);
+       pr_err("ECC Chunk Count        : %u\n", geo->ecc_chunk_count);
+       pr_err("Payload Size in Bytes  : %u\n", geo->payload_size);
+       pr_err("Auxiliary Size in Bytes: %u\n", geo->auxiliary_size);
+       pr_err("Auxiliary Status Offset: %u\n", geo->auxiliary_status_offset);
+       pr_err("Block Mark Byte Offset : %u\n", geo->block_mark_byte_offset);
+       pr_err("Block Mark Bit Offset  : %u\n", geo->block_mark_bit_offset);
+}
+
+/* Configures the geometry for BCH.  */
+int bch_set_geometry(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+       struct bch_geometry *bch_geo = &this->bch_geometry;
+       unsigned int block_count;
+       unsigned int block_size;
+       unsigned int metadata_size;
+       unsigned int ecc_strength;
+       unsigned int page_size;
+       int ret;
+
+       if (common_nfc_set_geometry(this))
+               return !0;
+
+       block_count   = bch_geo->ecc_chunk_count - 1;
+       block_size    = bch_geo->ecc_chunk_size;
+       metadata_size = bch_geo->metadata_size;
+       ecc_strength  = bch_geo->ecc_strength >> 1;
+       page_size     = bch_geo->page_size;
+
+       ret = clk_enable(r->clock);
+       if (ret)
+               goto err_out;
+
+       ret = gpmi_reset_block(r->bch_regs, true);
+       if (ret)
+               goto err_out;
+
+       /* Configure layout 0. */
+       writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count)
+                       | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
+                       | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength)
+                       | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size),
+                       r->bch_regs + HW_BCH_FLASH0LAYOUT0);
+
+       writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
+                       | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength)
+                       | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size),
+                       r->bch_regs + HW_BCH_FLASH0LAYOUT1);
+
+       /* Set *all* chip selects to use layout 0. */
+       writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
+
+       /* Enable interrupts. */
+       writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
+                               r->bch_regs + HW_BCH_CTRL_SET);
+
+       clk_disable(r->clock);
+       return 0;
+err_out:
+       return ret;
+}
+
+/* Converts time in nanoseconds to cycles. */
+static unsigned int ns_to_cycles(unsigned int time,
+                       unsigned int period, unsigned int min)
+{
+       unsigned int k;
+
+       k = (time + period - 1) / period;
+       return max(k, min);
+}
+
+/* Apply timing to current hardware conditions. */
+static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
+                                       struct gpmi_nfc_hardware_timing *hw)
+{
+       struct gpmi_nand_platform_data *pdata = this->pdata;
+       struct timing_threshod *nfc = &timing_default_threshold;
+       struct nand_chip *nand = &this->nand;
+       struct nand_timing target = this->timing;
+       bool improved_timing_is_available;
+       unsigned long clock_frequency_in_hz;
+       unsigned int clock_period_in_ns;
+       bool dll_use_half_periods;
+       unsigned int dll_delay_shift;
+       unsigned int max_sample_delay_in_ns;
+       unsigned int address_setup_in_cycles;
+       unsigned int data_setup_in_ns;
+       unsigned int data_setup_in_cycles;
+       unsigned int data_hold_in_cycles;
+       int ideal_sample_delay_in_ns;
+       unsigned int sample_delay_factor;
+       int tEYE;
+       unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns;
+       unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns;
+
+       /*
+        * If there are multiple chips, we need to relax the timings to allow
+        * for signal distortion due to higher capacitance.
+        */
+       if (nand->numchips > 2) {
+               target.data_setup_in_ns    += 10;
+               target.data_hold_in_ns     += 10;
+               target.address_setup_in_ns += 10;
+       } else if (nand->numchips > 1) {
+               target.data_setup_in_ns    += 5;
+               target.data_hold_in_ns     += 5;
+               target.address_setup_in_ns += 5;
+       }
+
+       /* Check if improved timing information is available. */
+       improved_timing_is_available =
+               (target.tREA_in_ns  >= 0) &&
+               (target.tRLOH_in_ns >= 0) &&
+               (target.tRHOH_in_ns >= 0) ;
+
+       /* Inspect the clock. */
+       clock_frequency_in_hz = nfc->clock_frequency_in_hz;
+       clock_period_in_ns    = 1000000000 / clock_frequency_in_hz;
+
+       /*
+        * The NFC quantizes setup and hold parameters in terms of clock cycles.
+        * Here, we quantize the setup and hold timing parameters to the
+        * next-highest clock period to make sure we apply at least the
+        * specified times.
+        *
+        * For data setup and data hold, the hardware interprets a value of zero
+        * as the largest possible delay. This is not what's intended by a zero
+        * in the input parameter, so we impose a minimum of one cycle.
+        */
+       data_setup_in_cycles    = ns_to_cycles(target.data_setup_in_ns,
+                                                       clock_period_in_ns, 1);
+       data_hold_in_cycles     = ns_to_cycles(target.data_hold_in_ns,
+                                                       clock_period_in_ns, 1);
+       address_setup_in_cycles = ns_to_cycles(target.address_setup_in_ns,
+                                                       clock_period_in_ns, 0);
+
+       /*
+        * The clock's period affects the sample delay in a number of ways:
+        *
+        * (1) The NFC HAL tells us the maximum clock period the sample delay
+        *     DLL can tolerate. If the clock period is greater than half that
+        *     maximum, we must configure the DLL to be driven by half periods.
+        *
+        * (2) We need to convert from an ideal sample delay, in ns, to a
+        *     "sample delay factor," which the NFC uses. This factor depends on
+        *     whether we're driving the DLL with full or half periods.
+        *     Paraphrasing the reference manual:
+        *
+        *         AD = SDF x 0.125 x RP
+        *
+        * where:
+        *
+        *     AD   is the applied delay, in ns.
+        *     SDF  is the sample delay factor, which is dimensionless.
+        *     RP   is the reference period, in ns, which is a full clock period
+        *          if the DLL is being driven by full periods, or half that if
+        *          the DLL is being driven by half periods.
+        *
+        * Let's re-arrange this in a way that's more useful to us:
+        *
+        *                        8
+        *         SDF  =  AD x ----
+        *                       RP
+        *
+        * The reference period is either the clock period or half that, so this
+        * is:
+        *
+        *                        8       AD x DDF
+        *         SDF  =  AD x -----  =  --------
+        *                      f x P        P
+        *
+        * where:
+        *
+        *       f  is 1 or 1/2, depending on how we're driving the DLL.
+        *       P  is the clock period.
+        *     DDF  is the DLL Delay Factor, a dimensionless value that
+        *          incorporates all the constants in the conversion.
+        *
+        * DDF will be either 8 or 16, both of which are powers of two. We can
+        * reduce the cost of this conversion by using bit shifts instead of
+        * multiplication or division. Thus:
+        *
+        *                 AD << DDS
+        *         SDF  =  ---------
+        *                     P
+        *
+        *     or
+        *
+        *         AD  =  (SDF >> DDS) x P
+        *
+        * where:
+        *
+        *     DDS  is the DLL Delay Shift, the logarithm to base 2 of the DDF.
+        */
+       if (clock_period_in_ns > (nfc->max_dll_clock_period_in_ns >> 1)) {
+               dll_use_half_periods = true;
+               dll_delay_shift      = 3 + 1;
+       } else {
+               dll_use_half_periods = false;
+               dll_delay_shift      = 3;
+       }
+
+       /*
+        * Compute the maximum sample delay the NFC allows, under current
+        * conditions. If the clock is running too slowly, no sample delay is
+        * possible.
+        */
+       if (clock_period_in_ns > nfc->max_dll_clock_period_in_ns)
+               max_sample_delay_in_ns = 0;
+       else {
+               /*
+                * Compute the delay implied by the largest sample delay factor
+                * the NFC allows.
+                */
+               max_sample_delay_in_ns =
+                       (nfc->max_sample_delay_factor * clock_period_in_ns) >>
+                                                               dll_delay_shift;
+
+               /*
+                * Check if the implied sample delay larger than the NFC
+                * actually allows.
+                */
+               if (max_sample_delay_in_ns > nfc->max_dll_delay_in_ns)
+                       max_sample_delay_in_ns = nfc->max_dll_delay_in_ns;
+       }
+
+       /*
+        * Check if improved timing information is available. If not, we have to
+        * use a less-sophisticated algorithm.
+        */
+       if (!improved_timing_is_available) {
+               /*
+                * Fold the read setup time required by the NFC into the ideal
+                * sample delay.
+                */
+               ideal_sample_delay_in_ns = target.gpmi_sample_delay_in_ns +
+                                               nfc->internal_data_setup_in_ns;
+
+               /*
+                * The ideal sample delay may be greater than the maximum
+                * allowed by the NFC. If so, we can trade off sample delay time
+                * for more data setup time.
+                *
+                * In each iteration of the following loop, we add a cycle to
+                * the data setup time and subtract a corresponding amount from
+                * the sample delay until we've satisified the constraints or
+                * can't do any better.
+                */
+               while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) &&
+                       (data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+
+                       data_setup_in_cycles++;
+                       ideal_sample_delay_in_ns -= clock_period_in_ns;
+
+                       if (ideal_sample_delay_in_ns < 0)
+                               ideal_sample_delay_in_ns = 0;
+
+               }
+
+               /*
+                * Compute the sample delay factor that corresponds most closely
+                * to the ideal sample delay. If the result is too large for the
+                * NFC, use the maximum value.
+                *
+                * Notice that we use the ns_to_cycles function to compute the
+                * sample delay factor. We do this because the form of the
+                * computation is the same as that for calculating cycles.
+                */
+               sample_delay_factor =
+                       ns_to_cycles(
+                               ideal_sample_delay_in_ns << dll_delay_shift,
+                                                       clock_period_in_ns, 0);
+
+               if (sample_delay_factor > nfc->max_sample_delay_factor)
+                       sample_delay_factor = nfc->max_sample_delay_factor;
+
+               /* Skip to the part where we return our results. */
+               goto return_results;
+       }
+
+       /*
+        * If control arrives here, we have more detailed timing information,
+        * so we can use a better algorithm.
+        */
+
+       /*
+        * Fold the read setup time required by the NFC into the maximum
+        * propagation delay.
+        */
+       max_prop_delay_in_ns += nfc->internal_data_setup_in_ns;
+
+       /*
+        * Earlier, we computed the number of clock cycles required to satisfy
+        * the data setup time. Now, we need to know the actual nanoseconds.
+        */
+       data_setup_in_ns = clock_period_in_ns * data_setup_in_cycles;
+
+       /*
+        * Compute tEYE, the width of the data eye when reading from the NAND
+        * Flash. The eye width is fundamentally determined by the data setup
+        * time, perturbed by propagation delays and some characteristics of the
+        * NAND Flash device.
+        *
+        * start of the eye = max_prop_delay + tREA
+        * end of the eye   = min_prop_delay + tRHOH + data_setup
+        */
+       tEYE = (int)min_prop_delay_in_ns + (int)target.tRHOH_in_ns +
+                                                       (int)data_setup_in_ns;
+
+       tEYE -= (int)max_prop_delay_in_ns + (int)target.tREA_in_ns;
+
+       /*
+        * The eye must be open. If it's not, we can try to open it by
+        * increasing its main forcer, the data setup time.
+        *
+        * In each iteration of the following loop, we increase the data setup
+        * time by a single clock cycle. We do this until either the eye is
+        * open or we run into NFC limits.
+        */
+       while ((tEYE <= 0) &&
+                       (data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+               /* Give a cycle to data setup. */
+               data_setup_in_cycles++;
+               /* Synchronize the data setup time with the cycles. */
+               data_setup_in_ns += clock_period_in_ns;
+               /* Adjust tEYE accordingly. */
+               tEYE += clock_period_in_ns;
+       }
+
+       /*
+        * When control arrives here, the eye is open. The ideal time to sample
+        * the data is in the center of the eye:
+        *
+        *     end of the eye + start of the eye
+        *     ---------------------------------  -  data_setup
+        *                    2
+        *
+        * After some algebra, this simplifies to the code immediately below.
+        */
+       ideal_sample_delay_in_ns =
+               ((int)max_prop_delay_in_ns +
+                       (int)target.tREA_in_ns +
+                               (int)min_prop_delay_in_ns +
+                                       (int)target.tRHOH_in_ns -
+                                               (int)data_setup_in_ns) >> 1;
+
+       /*
+        * The following figure illustrates some aspects of a NAND Flash read:
+        *
+        *
+        *           __                   _____________________________________
+        * RDN         \_________________/
+        *
+        *                                         <---- tEYE ----->
+        *                                        /-----------------\
+        * Read Data ----------------------------<                   >---------
+        *                                        \-----------------/
+        *             ^                 ^                 ^              ^
+        *             |                 |                 |              |
+        *             |<--Data Setup -->|<--Delay Time -->|              |
+        *             |                 |                 |              |
+        *             |                 |                                |
+        *             |                 |<--   Quantized Delay Time   -->|
+        *             |                 |                                |
+        *
+        *
+        * We have some issues we must now address:
+        *
+        * (1) The *ideal* sample delay time must not be negative. If it is, we
+        *     jam it to zero.
+        *
+        * (2) The *ideal* sample delay time must not be greater than that
+        *     allowed by the NFC. If it is, we can increase the data setup
+        *     time, which will reduce the delay between the end of the data
+        *     setup and the center of the eye. It will also make the eye
+        *     larger, which might help with the next issue...
+        *
+        * (3) The *quantized* sample delay time must not fall either before the
+        *     eye opens or after it closes (the latter is the problem
+        *     illustrated in the above figure).
+        */
+
+       /* Jam a negative ideal sample delay to zero. */
+       if (ideal_sample_delay_in_ns < 0)
+               ideal_sample_delay_in_ns = 0;
+
+       /*
+        * Extend the data setup as needed to reduce the ideal sample delay
+        * below the maximum permitted by the NFC.
+        */
+       while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) &&
+                       (data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+
+               /* Give a cycle to data setup. */
+               data_setup_in_cycles++;
+               /* Synchronize the data setup time with the cycles. */
+               data_setup_in_ns += clock_period_in_ns;
+               /* Adjust tEYE accordingly. */
+               tEYE += clock_period_in_ns;
+
+               /*
+                * Decrease the ideal sample delay by one half cycle, to keep it
+                * in the middle of the eye.
+                */
+               ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1);
+
+               /* Jam a negative ideal sample delay to zero. */
+               if (ideal_sample_delay_in_ns < 0)
+                       ideal_sample_delay_in_ns = 0;
+       }
+
+       /*
+        * Compute the sample delay factor that corresponds to the ideal sample
+        * delay. If the result is too large, then use the maximum allowed
+        * value.
+        *
+        * Notice that we use the ns_to_cycles function to compute the sample
+        * delay factor. We do this because the form of the computation is the
+        * same as that for calculating cycles.
+        */
+       sample_delay_factor =
+               ns_to_cycles(ideal_sample_delay_in_ns << dll_delay_shift,
+                                                       clock_period_in_ns, 0);
+
+       if (sample_delay_factor > nfc->max_sample_delay_factor)
+               sample_delay_factor = nfc->max_sample_delay_factor;
+
+       /*
+        * These macros conveniently encapsulate a computation we'll use to
+        * continuously evaluate whether or not the data sample delay is inside
+        * the eye.
+        */
+       #define IDEAL_DELAY  ((int) ideal_sample_delay_in_ns)
+
+       #define QUANTIZED_DELAY  \
+               ((int) ((sample_delay_factor * clock_period_in_ns) >> \
+                                                       dll_delay_shift))
+
+       #define DELAY_ERROR  (abs(QUANTIZED_DELAY - IDEAL_DELAY))
+
+       #define SAMPLE_IS_NOT_WITHIN_THE_EYE  (DELAY_ERROR > (tEYE >> 1))
+
+       /*
+        * While the quantized sample time falls outside the eye, reduce the
+        * sample delay or extend the data setup to move the sampling point back
+        * toward the eye. Do not allow the number of data setup cycles to
+        * exceed the maximum allowed by the NFC.
+        */
+       while (SAMPLE_IS_NOT_WITHIN_THE_EYE &&
+                       (data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+               /*
+                * If control arrives here, the quantized sample delay falls
+                * outside the eye. Check if it's before the eye opens, or after
+                * the eye closes.
+                */
+               if (QUANTIZED_DELAY > IDEAL_DELAY) {
+                       /*
+                        * If control arrives here, the quantized sample delay
+                        * falls after the eye closes. Decrease the quantized
+                        * delay time and then go back to re-evaluate.
+                        */
+                       if (sample_delay_factor != 0)
+                               sample_delay_factor--;
+                       continue;
+               }
+
+               /*
+                * If control arrives here, the quantized sample delay falls
+                * before the eye opens. Shift the sample point by increasing
+                * data setup time. This will also make the eye larger.
+                */
+
+               /* Give a cycle to data setup. */
+               data_setup_in_cycles++;
+               /* Synchronize the data setup time with the cycles. */
+               data_setup_in_ns += clock_period_in_ns;
+               /* Adjust tEYE accordingly. */
+               tEYE += clock_period_in_ns;
+
+               /*
+                * Decrease the ideal sample delay by one half cycle, to keep it
+                * in the middle of the eye.
+                */
+               ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1);
+
+               /* ...and one less period for the delay time. */
+               ideal_sample_delay_in_ns -= clock_period_in_ns;
+
+               /* Jam a negative ideal sample delay to zero. */
+               if (ideal_sample_delay_in_ns < 0)
+                       ideal_sample_delay_in_ns = 0;
+
+               /*
+                * We have a new ideal sample delay, so re-compute the quantized
+                * delay.
+                */
+               sample_delay_factor =
+                       ns_to_cycles(
+                               ideal_sample_delay_in_ns << dll_delay_shift,
+                                                       clock_period_in_ns, 0);
+
+               if (sample_delay_factor > nfc->max_sample_delay_factor)
+                       sample_delay_factor = nfc->max_sample_delay_factor;
+       }
+
+       /* Control arrives here when we're ready to return our results. */
+return_results:
+       hw->data_setup_in_cycles    = data_setup_in_cycles;
+       hw->data_hold_in_cycles     = data_hold_in_cycles;
+       hw->address_setup_in_cycles = address_setup_in_cycles;
+       hw->use_half_periods        = dll_use_half_periods;
+       hw->sample_delay_factor     = sample_delay_factor;
+
+       /* Return success. */
+       return 0;
+}
+
+/* Begin the I/O */
+void gpmi_begin(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+       struct timing_threshod *nfc = &timing_default_threshold;
+       unsigned char  *gpmi_regs = r->gpmi_regs;
+       unsigned int   clock_period_in_ns;
+       uint32_t       reg;
+       unsigned int   dll_wait_time_in_us;
+       struct gpmi_nfc_hardware_timing  hw;
+       int ret;
+
+       /* Enable the clock. */
+       ret = clk_enable(r->clock);
+       if (ret) {
+               pr_err("We failed in enable the clk\n");
+               goto err_out;
+       }
+
+       /* set ready/busy timeout */
+       writel(0x500 << BP_GPMI_TIMING1_BUSY_TIMEOUT,
+               gpmi_regs + HW_GPMI_TIMING1);
+
+       /* Get the timing information we need. */
+       nfc->clock_frequency_in_hz = clk_get_rate(r->clock);
+       clock_period_in_ns = 1000000000 / nfc->clock_frequency_in_hz;
+
+       gpmi_nfc_compute_hardware_timing(this, &hw);
+
+       /* Set up all the simple timing parameters. */
+       reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) |
+               BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles)         |
+               BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles)       ;
+
+       writel(reg, gpmi_regs + HW_GPMI_TIMING0);
+
+       /*
+        * DLL_ENABLE must be set to 0 when setting RDN_DELAY or HALF_PERIOD.
+        */
+       writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+       /* Clear out the DLL control fields. */
+       writel(BM_GPMI_CTRL1_RDN_DELAY,   gpmi_regs + HW_GPMI_CTRL1_CLR);
+       writel(BM_GPMI_CTRL1_HALF_PERIOD, gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+       /* If no sample delay is called for, return immediately. */
+       if (!hw.sample_delay_factor)
+               return;
+
+       /* Configure the HALF_PERIOD flag. */
+       if (hw.use_half_periods)
+               writel(BM_GPMI_CTRL1_HALF_PERIOD,
+                                               gpmi_regs + HW_GPMI_CTRL1_SET);
+
+       /* Set the delay factor. */
+       writel(BF_GPMI_CTRL1_RDN_DELAY(hw.sample_delay_factor),
+                                               gpmi_regs + HW_GPMI_CTRL1_SET);
+
+       /* Enable the DLL. */
+       writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_SET);
+
+       /*
+        * After we enable the GPMI DLL, we have to wait 64 clock cycles before
+        * we can use the GPMI.
+        *
+        * Calculate the amount of time we need to wait, in microseconds.
+        */
+       dll_wait_time_in_us = (clock_period_in_ns * 64) / 1000;
+
+       if (!dll_wait_time_in_us)
+               dll_wait_time_in_us = 1;
+
+       /* Wait for the DLL to settle. */
+       udelay(dll_wait_time_in_us);
+
+err_out:
+       return;
+}
+
+void gpmi_end(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+       clk_disable(r->clock);
+}
+
+/* Clears a BCH interrupt. */
+void gpmi_clear_bch(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+       writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR);
+}
+
+/* Returns the Ready/Busy status of the given chip. */
+int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
+{
+       struct resources *r = &this->resources;
+       uint32_t mask = 0;
+       uint32_t reg = 0;
+
+       if (GPMI_IS_MX23(this)) {
+               mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
+               reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
+       } else if (GPMI_IS_MX28(this)) {
+               mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
+               reg = readl(r->gpmi_regs + HW_GPMI_STAT);
+       } else
+               pr_err("unknow arch.\n");
+       return reg & mask;
+}
+
+static inline void set_dma_type(struct gpmi_nand_data *this,
+                                       enum dma_ops_type type)
+{
+       this->last_dma_type = this->dma_type;
+       this->dma_type = type;
+}
+
+int gpmi_send_command(struct gpmi_nand_data *this)
+{
+       struct dma_chan *channel = get_dma_chan(this);
+       struct dma_async_tx_descriptor *desc;
+       struct scatterlist *sgl;
+       int chip = this->current_chip;
+       u32 pio[3];
+
+       /* [1] send out the PIO words */
+       pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE)
+               | BM_GPMI_CTRL0_WORD_LENGTH
+               | BF_GPMI_CTRL0_CS(chip, this)
+               | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+               | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_CLE)
+               | BM_GPMI_CTRL0_ADDRESS_INCREMENT
+               | BF_GPMI_CTRL0_XFER_COUNT(this->command_length);
+       pio[1] = pio[2] = 0;
+       desc = channel->device->device_prep_slave_sg(channel,
+                                       (struct scatterlist *)pio,
+                                       ARRAY_SIZE(pio), DMA_NONE, 0);
+       if (!desc) {
+               pr_err("step 1 error\n");
+               return -1;
+       }
+
+       /* [2] send out the COMMAND + ADDRESS string stored in @buffer */
+       sgl = &this->cmd_sgl;
+
+       sg_init_one(sgl, this->cmd_buffer, this->command_length);
+       dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
+       desc = channel->device->device_prep_slave_sg(channel,
+                                       sgl, 1, DMA_TO_DEVICE, 1);
+       if (!desc) {
+               pr_err("step 2 error\n");
+               return -1;
+       }
+
+       /* [3] submit the DMA */
+       set_dma_type(this, DMA_FOR_COMMAND);
+       return start_dma_without_bch_irq(this, desc);
+}
+
+int gpmi_send_data(struct gpmi_nand_data *this)
+{
+       struct dma_async_tx_descriptor *desc;
+       struct dma_chan *channel = get_dma_chan(this);
+       int chip = this->current_chip;
+       uint32_t command_mode;
+       uint32_t address;
+       u32 pio[2];
+
+       /* [1] PIO */
+       command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
+       address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+       pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+               | BM_GPMI_CTRL0_WORD_LENGTH
+               | BF_GPMI_CTRL0_CS(chip, this)
+               | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+               | BF_GPMI_CTRL0_ADDRESS(address)
+               | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len);
+       pio[1] = 0;
+       desc = channel->device->device_prep_slave_sg(channel,
+                                       (struct scatterlist *)pio,
+                                       ARRAY_SIZE(pio), DMA_NONE, 0);
+       if (!desc) {
+               pr_err("step 1 error\n");
+               return -1;
+       }
+
+       /* [2] send DMA request */
+       prepare_data_dma(this, DMA_TO_DEVICE);
+       desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl,
+                                               1, DMA_TO_DEVICE, 1);
+       if (!desc) {
+               pr_err("step 2 error\n");
+               return -1;
+       }
+       /* [3] submit the DMA */
+       set_dma_type(this, DMA_FOR_WRITE_DATA);
+       return start_dma_without_bch_irq(this, desc);
+}
+
+int gpmi_read_data(struct gpmi_nand_data *this)
+{
+       struct dma_async_tx_descriptor *desc;
+       struct dma_chan *channel = get_dma_chan(this);
+       int chip = this->current_chip;
+       u32 pio[2];
+
+       /* [1] : send PIO */
+       pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ)
+               | BM_GPMI_CTRL0_WORD_LENGTH
+               | BF_GPMI_CTRL0_CS(chip, this)
+               | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+               | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
+               | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len);
+       pio[1] = 0;
+       desc = channel->device->device_prep_slave_sg(channel,
+                                       (struct scatterlist *)pio,
+                                       ARRAY_SIZE(pio), DMA_NONE, 0);
+       if (!desc) {
+               pr_err("step 1 error\n");
+               return -1;
+       }
+
+       /* [2] : send DMA request */
+       prepare_data_dma(this, DMA_FROM_DEVICE);
+       desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl,
+                                               1, DMA_FROM_DEVICE, 1);
+       if (!desc) {
+               pr_err("step 2 error\n");
+               return -1;
+       }
+
+       /* [3] : submit the DMA */
+       set_dma_type(this, DMA_FOR_READ_DATA);
+       return start_dma_without_bch_irq(this, desc);
+}
+
+int gpmi_send_page(struct gpmi_nand_data *this,
+                       dma_addr_t payload, dma_addr_t auxiliary)
+{
+       struct bch_geometry *geo = &this->bch_geometry;
+       uint32_t command_mode;
+       uint32_t address;
+       uint32_t ecc_command;
+       uint32_t buffer_mask;
+       struct dma_async_tx_descriptor *desc;
+       struct dma_chan *channel = get_dma_chan(this);
+       int chip = this->current_chip;
+       u32 pio[6];
+
+       /* A DMA descriptor that does an ECC page read. */
+       command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
+       address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+       ecc_command  = BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE;
+       buffer_mask  = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE |
+                               BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
+
+       pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+               | BM_GPMI_CTRL0_WORD_LENGTH
+               | BF_GPMI_CTRL0_CS(chip, this)
+               | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+               | BF_GPMI_CTRL0_ADDRESS(address)
+               | BF_GPMI_CTRL0_XFER_COUNT(0);
+       pio[1] = 0;
+       pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
+               | BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
+               | BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
+       pio[3] = geo->page_size;
+       pio[4] = payload;
+       pio[5] = auxiliary;
+
+       desc = channel->device->device_prep_slave_sg(channel,
+                                       (struct scatterlist *)pio,
+                                       ARRAY_SIZE(pio), DMA_NONE, 0);
+       if (!desc) {
+               pr_err("step 2 error\n");
+               return -1;
+       }
+       set_dma_type(this, DMA_FOR_WRITE_ECC_PAGE);
+       return start_dma_with_bch_irq(this, desc);
+}
+
+int gpmi_read_page(struct gpmi_nand_data *this,
+                               dma_addr_t payload, dma_addr_t auxiliary)
+{
+       struct bch_geometry *geo = &this->bch_geometry;
+       uint32_t command_mode;
+       uint32_t address;
+       uint32_t ecc_command;
+       uint32_t buffer_mask;
+       struct dma_async_tx_descriptor *desc;
+       struct dma_chan *channel = get_dma_chan(this);
+       int chip = this->current_chip;
+       u32 pio[6];
+
+       /* [1] Wait for the chip to report ready. */
+       command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
+       address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+       pio[0] =  BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+               | BM_GPMI_CTRL0_WORD_LENGTH
+               | BF_GPMI_CTRL0_CS(chip, this)
+               | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+               | BF_GPMI_CTRL0_ADDRESS(address)
+               | BF_GPMI_CTRL0_XFER_COUNT(0);
+       pio[1] = 0;
+       desc = channel->device->device_prep_slave_sg(channel,
+                               (struct scatterlist *)pio, 2, DMA_NONE, 0);
+       if (!desc) {
+               pr_err("step 1 error\n");
+               return -1;
+       }
+
+       /* [2] Enable the BCH block and read. */
+       command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
+       address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+       ecc_command  = BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE;
+       buffer_mask  = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE
+                       | BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
+
+       pio[0] =  BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+               | BM_GPMI_CTRL0_WORD_LENGTH
+               | BF_GPMI_CTRL0_CS(chip, this)
+               | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+               | BF_GPMI_CTRL0_ADDRESS(address)
+               | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
+
+       pio[1] = 0;
+       pio[2] =  BM_GPMI_ECCCTRL_ENABLE_ECC
+               | BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
+               | BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
+       pio[3] = geo->page_size;
+       pio[4] = payload;
+       pio[5] = auxiliary;
+       desc = channel->device->device_prep_slave_sg(channel,
+                                       (struct scatterlist *)pio,
+                                       ARRAY_SIZE(pio), DMA_NONE, 1);
+       if (!desc) {
+               pr_err("step 2 error\n");
+               return -1;
+       }
+
+       /* [3] Disable the BCH block */
+       command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
+       address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+       pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+               | BM_GPMI_CTRL0_WORD_LENGTH
+               | BF_GPMI_CTRL0_CS(chip, this)
+               | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+               | BF_GPMI_CTRL0_ADDRESS(address)
+               | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
+       pio[1] = 0;
+       desc = channel->device->device_prep_slave_sg(channel,
+                               (struct scatterlist *)pio, 2, DMA_NONE, 1);
+       if (!desc) {
+               pr_err("step 3 error\n");
+               return -1;
+       }
+
+       /* [4] submit the DMA */
+       set_dma_type(this, DMA_FOR_READ_ECC_PAGE);
+       return start_dma_with_bch_irq(this, desc);
+}
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
new file mode 100644 (file)
index 0000000..071b634
--- /dev/null
@@ -0,0 +1,1619 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/gpmi-nand.h>
+#include <linux/mtd/partitions.h>
+
+#include "gpmi-nand.h"
+
+/* add our owner bbt descriptor */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr gpmi_bbt_descr = {
+       .options        = 0,
+       .offs           = 0,
+       .len            = 1,
+       .pattern        = scan_ff_pattern
+};
+
+/*  We will use all the (page + OOB). */
+static struct nand_ecclayout gpmi_hw_ecclayout = {
+       .eccbytes = 0,
+       .eccpos = { 0, },
+       .oobfree = { {.offset = 0, .length = 0} }
+};
+
+static irqreturn_t bch_irq(int irq, void *cookie)
+{
+       struct gpmi_nand_data *this = cookie;
+
+       gpmi_clear_bch(this);
+       complete(&this->bch_done);
+       return IRQ_HANDLED;
+}
+
+/*
+ *  Calculate the ECC strength by hand:
+ *     E : The ECC strength.
+ *     G : the length of Galois Field.
+ *     N : The chunk count of per page.
+ *     O : the oobsize of the NAND chip.
+ *     M : the metasize of per page.
+ *
+ *     The formula is :
+ *             E * G * N
+ *           ------------ <= (O - M)
+ *                  8
+ *
+ *      So, we get E by:
+ *                    (O - M) * 8
+ *              E <= -------------
+ *                       G * N
+ */
+static inline int get_ecc_strength(struct gpmi_nand_data *this)
+{
+       struct bch_geometry *geo = &this->bch_geometry;
+       struct mtd_info *mtd = &this->mtd;
+       int ecc_strength;
+
+       ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8)
+                       / (geo->gf_len * geo->ecc_chunk_count);
+
+       /* We need the minor even number. */
+       return round_down(ecc_strength, 2);
+}
+
+int common_nfc_set_geometry(struct gpmi_nand_data *this)
+{
+       struct bch_geometry *geo = &this->bch_geometry;
+       struct mtd_info *mtd = &this->mtd;
+       unsigned int metadata_size;
+       unsigned int status_size;
+       unsigned int block_mark_bit_offset;
+
+       /*
+        * The size of the metadata can be changed, though we set it to 10
+        * bytes now. But it can't be too large, because we have to save
+        * enough space for BCH.
+        */
+       geo->metadata_size = 10;
+
+       /* The default for the length of Galois Field. */
+       geo->gf_len = 13;
+
+       /* The default for chunk size. There is no oobsize greater then 512. */
+       geo->ecc_chunk_size = 512;
+       while (geo->ecc_chunk_size < mtd->oobsize)
+               geo->ecc_chunk_size *= 2; /* keep C >= O */
+
+       geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+
+       /* We use the same ECC strength for all chunks. */
+       geo->ecc_strength = get_ecc_strength(this);
+       if (!geo->ecc_strength) {
+               pr_err("We get a wrong ECC strength.\n");
+               return -EINVAL;
+       }
+
+       geo->page_size = mtd->writesize + mtd->oobsize;
+       geo->payload_size = mtd->writesize;
+
+       /*
+        * The auxiliary buffer contains the metadata and the ECC status. The
+        * metadata is padded to the nearest 32-bit boundary. The ECC status
+        * contains one byte for every ECC chunk, and is also padded to the
+        * nearest 32-bit boundary.
+        */
+       metadata_size = ALIGN(geo->metadata_size, 4);
+       status_size   = ALIGN(geo->ecc_chunk_count, 4);
+
+       geo->auxiliary_size = metadata_size + status_size;
+       geo->auxiliary_status_offset = metadata_size;
+
+       if (!this->swap_block_mark)
+               return 0;
+
+       /*
+        * We need to compute the byte and bit offsets of
+        * the physical block mark within the ECC-based view of the page.
+        *
+        * NAND chip with 2K page shows below:
+        *                                             (Block Mark)
+        *                                                   |      |
+        *                                                   |  D   |
+        *                                                   |<---->|
+        *                                                   V      V
+        *    +---+----------+-+----------+-+----------+-+----------+-+
+        *    | M |   data   |E|   data   |E|   data   |E|   data   |E|
+        *    +---+----------+-+----------+-+----------+-+----------+-+
+        *
+        * The position of block mark moves forward in the ECC-based view
+        * of page, and the delta is:
+        *
+        *                   E * G * (N - 1)
+        *             D = (---------------- + M)
+        *                          8
+        *
+        * With the formula to compute the ECC strength, and the condition
+        *       : C >= O         (C is the ecc chunk size)
+        *
+        * It's easy to deduce to the following result:
+        *
+        *         E * G       (O - M)      C - M         C - M
+        *      ----------- <= ------- <=  --------  <  ---------
+        *           8            N           N          (N - 1)
+        *
+        *  So, we get:
+        *
+        *                   E * G * (N - 1)
+        *             D = (---------------- + M) < C
+        *                          8
+        *
+        *  The above inequality means the position of block mark
+        *  within the ECC-based view of the page is still in the data chunk,
+        *  and it's NOT in the ECC bits of the chunk.
+        *
+        *  Use the following to compute the bit position of the
+        *  physical block mark within the ECC-based view of the page:
+        *          (page_size - D) * 8
+        *
+        *  --Huang Shijie
+        */
+       block_mark_bit_offset = mtd->writesize * 8 -
+               (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+                               + geo->metadata_size * 8);
+
+       geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+       geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
+       return 0;
+}
+
+struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
+{
+       int chipnr = this->current_chip;
+
+       return this->dma_chans[chipnr];
+}
+
+/* Can we use the upper's buffer directly for DMA? */
+void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
+{
+       struct scatterlist *sgl = &this->data_sgl;
+       int ret;
+
+       this->direct_dma_map_ok = true;
+
+       /* first try to map the upper buffer directly */
+       sg_init_one(sgl, this->upper_buf, this->upper_len);
+       ret = dma_map_sg(this->dev, sgl, 1, dr);
+       if (ret == 0) {
+               /* We have to use our own DMA buffer. */
+               sg_init_one(sgl, this->data_buffer_dma, PAGE_SIZE);
+
+               if (dr == DMA_TO_DEVICE)
+                       memcpy(this->data_buffer_dma, this->upper_buf,
+                               this->upper_len);
+
+               ret = dma_map_sg(this->dev, sgl, 1, dr);
+               if (ret == 0)
+                       pr_err("map failed.\n");
+
+               this->direct_dma_map_ok = false;
+       }
+}
+
+/* This will be called after the DMA operation is finished. */
+static void dma_irq_callback(void *param)
+{
+       struct gpmi_nand_data *this = param;
+       struct completion *dma_c = &this->dma_done;
+
+       complete(dma_c);
+
+       switch (this->dma_type) {
+       case DMA_FOR_COMMAND:
+               dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE);
+               break;
+
+       case DMA_FOR_READ_DATA:
+               dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_FROM_DEVICE);
+               if (this->direct_dma_map_ok == false)
+                       memcpy(this->upper_buf, this->data_buffer_dma,
+                               this->upper_len);
+               break;
+
+       case DMA_FOR_WRITE_DATA:
+               dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_TO_DEVICE);
+               break;
+
+       case DMA_FOR_READ_ECC_PAGE:
+       case DMA_FOR_WRITE_ECC_PAGE:
+               /* We have to wait the BCH interrupt to finish. */
+               break;
+
+       default:
+               pr_err("in wrong DMA operation.\n");
+       }
+}
+
+int start_dma_without_bch_irq(struct gpmi_nand_data *this,
+                               struct dma_async_tx_descriptor *desc)
+{
+       struct completion *dma_c = &this->dma_done;
+       int err;
+
+       init_completion(dma_c);
+
+       desc->callback          = dma_irq_callback;
+       desc->callback_param    = this;
+       dmaengine_submit(desc);
+
+       /* Wait for the interrupt from the DMA block. */
+       err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
+       if (!err) {
+               pr_err("DMA timeout, last DMA :%d\n", this->last_dma_type);
+               gpmi_dump_info(this);
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+/*
+ * This function is used in BCH reading or BCH writing pages.
+ * It will wait for the BCH interrupt as long as ONE second.
+ * Actually, we must wait for two interrupts :
+ *     [1] firstly the DMA interrupt and
+ *     [2] secondly the BCH interrupt.
+ */
+int start_dma_with_bch_irq(struct gpmi_nand_data *this,
+                       struct dma_async_tx_descriptor *desc)
+{
+       struct completion *bch_c = &this->bch_done;
+       int err;
+
+       /* Prepare to receive an interrupt from the BCH block. */
+       init_completion(bch_c);
+
+       /* start the DMA */
+       start_dma_without_bch_irq(this, desc);
+
+       /* Wait for the interrupt from the BCH block. */
+       err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
+       if (!err) {
+               pr_err("BCH timeout, last DMA :%d\n", this->last_dma_type);
+               gpmi_dump_info(this);
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+static int __devinit
+acquire_register_block(struct gpmi_nand_data *this, const char *res_name)
+{
+       struct platform_device *pdev = this->pdev;
+       struct resources *res = &this->resources;
+       struct resource *r;
+       void *p;
+
+       r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+       if (!r) {
+               pr_err("Can't get resource for %s\n", res_name);
+               return -ENXIO;
+       }
+
+       p = ioremap(r->start, resource_size(r));
+       if (!p) {
+               pr_err("Can't remap %s\n", res_name);
+               return -ENOMEM;
+       }
+
+       if (!strcmp(res_name, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME))
+               res->gpmi_regs = p;
+       else if (!strcmp(res_name, GPMI_NAND_BCH_REGS_ADDR_RES_NAME))
+               res->bch_regs = p;
+       else
+               pr_err("unknown resource name : %s\n", res_name);
+
+       return 0;
+}
+
+static void release_register_block(struct gpmi_nand_data *this)
+{
+       struct resources *res = &this->resources;
+       if (res->gpmi_regs)
+               iounmap(res->gpmi_regs);
+       if (res->bch_regs)
+               iounmap(res->bch_regs);
+       res->gpmi_regs = NULL;
+       res->bch_regs = NULL;
+}
+
+static int __devinit
+acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
+{
+       struct platform_device *pdev = this->pdev;
+       struct resources *res = &this->resources;
+       const char *res_name = GPMI_NAND_BCH_INTERRUPT_RES_NAME;
+       struct resource *r;
+       int err;
+
+       r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
+       if (!r) {
+               pr_err("Can't get resource for %s\n", res_name);
+               return -ENXIO;
+       }
+
+       err = request_irq(r->start, irq_h, 0, res_name, this);
+       if (err) {
+               pr_err("Can't own %s\n", res_name);
+               return err;
+       }
+
+       res->bch_low_interrupt = r->start;
+       res->bch_high_interrupt = r->end;
+       return 0;
+}
+
+static void release_bch_irq(struct gpmi_nand_data *this)
+{
+       struct resources *res = &this->resources;
+       int i = res->bch_low_interrupt;
+
+       for (; i <= res->bch_high_interrupt; i++)
+               free_irq(i, this);
+}
+
+static bool gpmi_dma_filter(struct dma_chan *chan, void *param)
+{
+       struct gpmi_nand_data *this = param;
+       struct resource *r = this->private;
+
+       if (!mxs_dma_is_apbh(chan))
+               return false;
+       /*
+        * only catch the GPMI dma channels :
+        *      for mx23 :      MX23_DMA_GPMI0 ~ MX23_DMA_GPMI3
+        *              (These four channels share the same IRQ!)
+        *
+        *      for mx28 :      MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7
+        *              (These eight channels share the same IRQ!)
+        */
+       if (r->start <= chan->chan_id && chan->chan_id <= r->end) {
+               chan->private = &this->dma_data;
+               return true;
+       }
+       return false;
+}
+
+static void release_dma_channels(struct gpmi_nand_data *this)
+{
+       unsigned int i;
+       for (i = 0; i < DMA_CHANS; i++)
+               if (this->dma_chans[i]) {
+                       dma_release_channel(this->dma_chans[i]);
+                       this->dma_chans[i] = NULL;
+               }
+}
+
+static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
+{
+       struct platform_device *pdev = this->pdev;
+       struct gpmi_nand_platform_data *pdata = this->pdata;
+       struct resources *res = &this->resources;
+       struct resource *r, *r_dma;
+       unsigned int i;
+
+       r = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+                                       GPMI_NAND_DMA_CHANNELS_RES_NAME);
+       r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+                                       GPMI_NAND_DMA_INTERRUPT_RES_NAME);
+       if (!r || !r_dma) {
+               pr_err("Can't get resource for DMA\n");
+               return -ENXIO;
+       }
+
+       /* used in gpmi_dma_filter() */
+       this->private = r;
+
+       for (i = r->start; i <= r->end; i++) {
+               struct dma_chan *dma_chan;
+               dma_cap_mask_t mask;
+
+               if (i - r->start >= pdata->max_chip_count)
+                       break;
+
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+
+               /* get the DMA interrupt */
+               if (r_dma->start == r_dma->end) {
+                       /* only register the first. */
+                       if (i == r->start)
+                               this->dma_data.chan_irq = r_dma->start;
+                       else
+                               this->dma_data.chan_irq = NO_IRQ;
+               } else
+                       this->dma_data.chan_irq = r_dma->start + (i - r->start);
+
+               dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
+               if (!dma_chan)
+                       goto acquire_err;
+
+               /* fill the first empty item */
+               this->dma_chans[i - r->start] = dma_chan;
+       }
+
+       res->dma_low_channel = r->start;
+       res->dma_high_channel = i;
+       return 0;
+
+acquire_err:
+       pr_err("Can't acquire DMA channel %u\n", i);
+       release_dma_channels(this);
+       return -EINVAL;
+}
+
+static int __devinit acquire_resources(struct gpmi_nand_data *this)
+{
+       struct resources *res = &this->resources;
+       int ret;
+
+       ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME);
+       if (ret)
+               goto exit_regs;
+
+       ret = acquire_register_block(this, GPMI_NAND_BCH_REGS_ADDR_RES_NAME);
+       if (ret)
+               goto exit_regs;
+
+       ret = acquire_bch_irq(this, bch_irq);
+       if (ret)
+               goto exit_regs;
+
+       ret = acquire_dma_channels(this);
+       if (ret)
+               goto exit_dma_channels;
+
+       res->clock = clk_get(&this->pdev->dev, NULL);
+       if (IS_ERR(res->clock)) {
+               pr_err("can not get the clock\n");
+               ret = -ENOENT;
+               goto exit_clock;
+       }
+       return 0;
+
+exit_clock:
+       release_dma_channels(this);
+exit_dma_channels:
+       release_bch_irq(this);
+exit_regs:
+       release_register_block(this);
+       return ret;
+}
+
+static void release_resources(struct gpmi_nand_data *this)
+{
+       struct resources *r = &this->resources;
+
+       clk_put(r->clock);
+       release_register_block(this);
+       release_bch_irq(this);
+       release_dma_channels(this);
+}
+
+static int __devinit init_hardware(struct gpmi_nand_data *this)
+{
+       int ret;
+
+       /*
+        * This structure contains the "safe" GPMI timing that should succeed
+        * with any NAND Flash device
+        * (although, with less-than-optimal performance).
+        */
+       struct nand_timing  safe_timing = {
+               .data_setup_in_ns        = 80,
+               .data_hold_in_ns         = 60,
+               .address_setup_in_ns     = 25,
+               .gpmi_sample_delay_in_ns =  6,
+               .tREA_in_ns              = -1,
+               .tRLOH_in_ns             = -1,
+               .tRHOH_in_ns             = -1,
+       };
+
+       /* Initialize the hardwares. */
+       ret = gpmi_init(this);
+       if (ret)
+               return ret;
+
+       this->timing = safe_timing;
+       return 0;
+}
+
+static int read_page_prepare(struct gpmi_nand_data *this,
+                       void *destination, unsigned length,
+                       void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+                       void **use_virt, dma_addr_t *use_phys)
+{
+       struct device *dev = this->dev;
+
+       if (virt_addr_valid(destination)) {
+               dma_addr_t dest_phys;
+
+               dest_phys = dma_map_single(dev, destination,
+                                               length, DMA_FROM_DEVICE);
+               if (dma_mapping_error(dev, dest_phys)) {
+                       if (alt_size < length) {
+                               pr_err("Alternate buffer is too small\n");
+                               return -ENOMEM;
+                       }
+                       goto map_failed;
+               }
+               *use_virt = destination;
+               *use_phys = dest_phys;
+               this->direct_dma_map_ok = true;
+               return 0;
+       }
+
+map_failed:
+       *use_virt = alt_virt;
+       *use_phys = alt_phys;
+       this->direct_dma_map_ok = false;
+       return 0;
+}
+
+static inline void read_page_end(struct gpmi_nand_data *this,
+                       void *destination, unsigned length,
+                       void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+                       void *used_virt, dma_addr_t used_phys)
+{
+       if (this->direct_dma_map_ok)
+               dma_unmap_single(this->dev, used_phys, length, DMA_FROM_DEVICE);
+}
+
+static inline void read_page_swap_end(struct gpmi_nand_data *this,
+                       void *destination, unsigned length,
+                       void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+                       void *used_virt, dma_addr_t used_phys)
+{
+       if (!this->direct_dma_map_ok)
+               memcpy(destination, alt_virt, length);
+}
+
+static int send_page_prepare(struct gpmi_nand_data *this,
+                       const void *source, unsigned length,
+                       void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+                       const void **use_virt, dma_addr_t *use_phys)
+{
+       struct device *dev = this->dev;
+
+       if (virt_addr_valid(source)) {
+               dma_addr_t source_phys;
+
+               source_phys = dma_map_single(dev, (void *)source, length,
+                                               DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, source_phys)) {
+                       if (alt_size < length) {
+                               pr_err("Alternate buffer is too small\n");
+                               return -ENOMEM;
+                       }
+                       goto map_failed;
+               }
+               *use_virt = source;
+               *use_phys = source_phys;
+               return 0;
+       }
+map_failed:
+       /*
+        * Copy the content of the source buffer into the alternate
+        * buffer and set up the return values accordingly.
+        */
+       memcpy(alt_virt, source, length);
+
+       *use_virt = alt_virt;
+       *use_phys = alt_phys;
+       return 0;
+}
+
+static void send_page_end(struct gpmi_nand_data *this,
+                       const void *source, unsigned length,
+                       void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+                       const void *used_virt, dma_addr_t used_phys)
+{
+       struct device *dev = this->dev;
+       if (used_virt == source)
+               dma_unmap_single(dev, used_phys, length, DMA_TO_DEVICE);
+}
+
+static void gpmi_free_dma_buffer(struct gpmi_nand_data *this)
+{
+       struct device *dev = this->dev;
+
+       if (this->page_buffer_virt && virt_addr_valid(this->page_buffer_virt))
+               dma_free_coherent(dev, this->page_buffer_size,
+                                       this->page_buffer_virt,
+                                       this->page_buffer_phys);
+       kfree(this->cmd_buffer);
+       kfree(this->data_buffer_dma);
+
+       this->cmd_buffer        = NULL;
+       this->data_buffer_dma   = NULL;
+       this->page_buffer_virt  = NULL;
+       this->page_buffer_size  =  0;
+}
+
+/* Allocate the DMA buffers */
+static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
+{
+       struct bch_geometry *geo = &this->bch_geometry;
+       struct device *dev = this->dev;
+
+       /* [1] Allocate a command buffer. PAGE_SIZE is enough. */
+       this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA);
+       if (this->cmd_buffer == NULL)
+               goto error_alloc;
+
+       /* [2] Allocate a read/write data buffer. PAGE_SIZE is enough. */
+       this->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA);
+       if (this->data_buffer_dma == NULL)
+               goto error_alloc;
+
+       /*
+        * [3] Allocate the page buffer.
+        *
+        * Both the payload buffer and the auxiliary buffer must appear on
+        * 32-bit boundaries. We presume the size of the payload buffer is a
+        * power of two and is much larger than four, which guarantees the
+        * auxiliary buffer will appear on a 32-bit boundary.
+        */
+       this->page_buffer_size = geo->payload_size + geo->auxiliary_size;
+       this->page_buffer_virt = dma_alloc_coherent(dev, this->page_buffer_size,
+                                       &this->page_buffer_phys, GFP_DMA);
+       if (!this->page_buffer_virt)
+               goto error_alloc;
+
+
+       /* Slice up the page buffer. */
+       this->payload_virt = this->page_buffer_virt;
+       this->payload_phys = this->page_buffer_phys;
+       this->auxiliary_virt = this->payload_virt + geo->payload_size;
+       this->auxiliary_phys = this->payload_phys + geo->payload_size;
+       return 0;
+
+error_alloc:
+       gpmi_free_dma_buffer(this);
+       pr_err("allocate DMA buffer ret!!\n");
+       return -ENOMEM;
+}
+
+static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct gpmi_nand_data *this = chip->priv;
+       int ret;
+
+       /*
+        * Every operation begins with a command byte and a series of zero or
+        * more address bytes. These are distinguished by either the Address
+        * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+        * asserted. When MTD is ready to execute the command, it will deassert
+        * both latch enables.
+        *
+        * Rather than run a separate DMA operation for every single byte, we
+        * queue them up and run a single DMA operation for the entire series
+        * of command and data bytes. NAND_CMD_NONE means the END of the queue.
+        */
+       if ((ctrl & (NAND_ALE | NAND_CLE))) {
+               if (data != NAND_CMD_NONE)
+                       this->cmd_buffer[this->command_length++] = data;
+               return;
+       }
+
+       if (!this->command_length)
+               return;
+
+       ret = gpmi_send_command(this);
+       if (ret)
+               pr_err("Chip: %u, Error %d\n", this->current_chip, ret);
+
+       this->command_length = 0;
+}
+
+static int gpmi_dev_ready(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct gpmi_nand_data *this = chip->priv;
+
+       return gpmi_is_ready(this, this->current_chip);
+}
+
+static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct gpmi_nand_data *this = chip->priv;
+
+       if ((this->current_chip < 0) && (chipnr >= 0))
+               gpmi_begin(this);
+       else if ((this->current_chip >= 0) && (chipnr < 0))
+               gpmi_end(this);
+
+       this->current_chip = chipnr;
+}
+
+static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct gpmi_nand_data *this = chip->priv;
+
+       pr_debug("len is %d\n", len);
+       this->upper_buf = buf;
+       this->upper_len = len;
+
+       gpmi_read_data(this);
+}
+
+static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct gpmi_nand_data *this = chip->priv;
+
+       pr_debug("len is %d\n", len);
+       this->upper_buf = (uint8_t *)buf;
+       this->upper_len = len;
+
+       gpmi_send_data(this);
+}
+
+static uint8_t gpmi_read_byte(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct gpmi_nand_data *this = chip->priv;
+       uint8_t *buf = this->data_buffer_dma;
+
+       gpmi_read_buf(mtd, buf, 1);
+       return buf[0];
+}
+
+/*
+ * Handles block mark swapping.
+ * It can be called in swapping the block mark, or swapping it back,
+ * because the the operations are the same.
+ */
+static void block_mark_swapping(struct gpmi_nand_data *this,
+                               void *payload, void *auxiliary)
+{
+       struct bch_geometry *nfc_geo = &this->bch_geometry;
+       unsigned char *p;
+       unsigned char *a;
+       unsigned int  bit;
+       unsigned char mask;
+       unsigned char from_data;
+       unsigned char from_oob;
+
+       if (!this->swap_block_mark)
+               return;
+
+       /*
+        * If control arrives here, we're swapping. Make some convenience
+        * variables.
+        */
+       bit = nfc_geo->block_mark_bit_offset;
+       p   = payload + nfc_geo->block_mark_byte_offset;
+       a   = auxiliary;
+
+       /*
+        * Get the byte from the data area that overlays the block mark. Since
+        * the ECC engine applies its own view to the bits in the page, the
+        * physical block mark won't (in general) appear on a byte boundary in
+        * the data.
+        */
+       from_data = (p[0] >> bit) | (p[1] << (8 - bit));
+
+       /* Get the byte from the OOB. */
+       from_oob = a[0];
+
+       /* Swap them. */
+       a[0] = from_data;
+
+       mask = (0x1 << bit) - 1;
+       p[0] = (p[0] & mask) | (from_oob << bit);
+
+       mask = ~0 << bit;
+       p[1] = (p[1] & mask) | (from_oob >> (8 - bit));
+}
+
+static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+                               uint8_t *buf, int page)
+{
+       struct gpmi_nand_data *this = chip->priv;
+       struct bch_geometry *nfc_geo = &this->bch_geometry;
+       void          *payload_virt;
+       dma_addr_t    payload_phys;
+       void          *auxiliary_virt;
+       dma_addr_t    auxiliary_phys;
+       unsigned int  i;
+       unsigned char *status;
+       unsigned int  failed;
+       unsigned int  corrected;
+       int           ret;
+
+       pr_debug("page number is : %d\n", page);
+       ret = read_page_prepare(this, buf, mtd->writesize,
+                                       this->payload_virt, this->payload_phys,
+                                       nfc_geo->payload_size,
+                                       &payload_virt, &payload_phys);
+       if (ret) {
+               pr_err("Inadequate DMA buffer\n");
+               ret = -ENOMEM;
+               return ret;
+       }
+       auxiliary_virt = this->auxiliary_virt;
+       auxiliary_phys = this->auxiliary_phys;
+
+       /* go! */
+       ret = gpmi_read_page(this, payload_phys, auxiliary_phys);
+       read_page_end(this, buf, mtd->writesize,
+                       this->payload_virt, this->payload_phys,
+                       nfc_geo->payload_size,
+                       payload_virt, payload_phys);
+       if (ret) {
+               pr_err("Error in ECC-based read: %d\n", ret);
+               goto exit_nfc;
+       }
+
+       /* handle the block mark swapping */
+       block_mark_swapping(this, payload_virt, auxiliary_virt);
+
+       /* Loop over status bytes, accumulating ECC status. */
+       failed          = 0;
+       corrected       = 0;
+       status          = auxiliary_virt + nfc_geo->auxiliary_status_offset;
+
+       for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) {
+               if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED))
+                       continue;
+
+               if (*status == STATUS_UNCORRECTABLE) {
+                       failed++;
+                       continue;
+               }
+               corrected += *status;
+       }
+
+       /*
+        * Propagate ECC status to the owning MTD only when failed or
+        * corrected times nearly reaches our ECC correction threshold.
+        */
+       if (failed || corrected >= (nfc_geo->ecc_strength - 1)) {
+               mtd->ecc_stats.failed    += failed;
+               mtd->ecc_stats.corrected += corrected;
+       }
+
+       /*
+        * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() for
+        * details about our policy for delivering the OOB.
+        *
+        * We fill the caller's buffer with set bits, and then copy the block
+        * mark to th caller's buffer. Note that, if block mark swapping was
+        * necessary, it has already been done, so we can rely on the first
+        * byte of the auxiliary buffer to contain the block mark.
+        */
+       memset(chip->oob_poi, ~0, mtd->oobsize);
+       chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
+
+       read_page_swap_end(this, buf, mtd->writesize,
+                       this->payload_virt, this->payload_phys,
+                       nfc_geo->payload_size,
+                       payload_virt, payload_phys);
+exit_nfc:
+       return ret;
+}
+
+static void gpmi_ecc_write_page(struct mtd_info *mtd,
+                               struct nand_chip *chip, const uint8_t *buf)
+{
+       struct gpmi_nand_data *this = chip->priv;
+       struct bch_geometry *nfc_geo = &this->bch_geometry;
+       const void *payload_virt;
+       dma_addr_t payload_phys;
+       const void *auxiliary_virt;
+       dma_addr_t auxiliary_phys;
+       int        ret;
+
+       pr_debug("ecc write page.\n");
+       if (this->swap_block_mark) {
+               /*
+                * If control arrives here, we're doing block mark swapping.
+                * Since we can't modify the caller's buffers, we must copy them
+                * into our own.
+                */
+               memcpy(this->payload_virt, buf, mtd->writesize);
+               payload_virt = this->payload_virt;
+               payload_phys = this->payload_phys;
+
+               memcpy(this->auxiliary_virt, chip->oob_poi,
+                               nfc_geo->auxiliary_size);
+               auxiliary_virt = this->auxiliary_virt;
+               auxiliary_phys = this->auxiliary_phys;
+
+               /* Handle block mark swapping. */
+               block_mark_swapping(this,
+                               (void *) payload_virt, (void *) auxiliary_virt);
+       } else {
+               /*
+                * If control arrives here, we're not doing block mark swapping,
+                * so we can to try and use the caller's buffers.
+                */
+               ret = send_page_prepare(this,
+                               buf, mtd->writesize,
+                               this->payload_virt, this->payload_phys,
+                               nfc_geo->payload_size,
+                               &payload_virt, &payload_phys);
+               if (ret) {
+                       pr_err("Inadequate payload DMA buffer\n");
+                       return;
+               }
+
+               ret = send_page_prepare(this,
+                               chip->oob_poi, mtd->oobsize,
+                               this->auxiliary_virt, this->auxiliary_phys,
+                               nfc_geo->auxiliary_size,
+                               &auxiliary_virt, &auxiliary_phys);
+               if (ret) {
+                       pr_err("Inadequate auxiliary DMA buffer\n");
+                       goto exit_auxiliary;
+               }
+       }
+
+       /* Ask the NFC. */
+       ret = gpmi_send_page(this, payload_phys, auxiliary_phys);
+       if (ret)
+               pr_err("Error in ECC-based write: %d\n", ret);
+
+       if (!this->swap_block_mark) {
+               send_page_end(this, chip->oob_poi, mtd->oobsize,
+                               this->auxiliary_virt, this->auxiliary_phys,
+                               nfc_geo->auxiliary_size,
+                               auxiliary_virt, auxiliary_phys);
+exit_auxiliary:
+               send_page_end(this, buf, mtd->writesize,
+                               this->payload_virt, this->payload_phys,
+                               nfc_geo->payload_size,
+                               payload_virt, payload_phys);
+       }
+}
+
+/*
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ *
+ * What we do for this specific read operation depends on two questions:
+ *
+ * 1) Are we doing a "raw" read, or an ECC-based read?
+ *
+ * 2) Are we using block mark swapping or transcription?
+ *
+ * There are four cases, illustrated by the following Karnaugh map:
+ *
+ *                    |           Raw           |         ECC-based       |
+ *       -------------+-------------------------+-------------------------+
+ *                    | Read the conventional   |                         |
+ *                    | OOB at the end of the   |                         |
+ *       Swapping     | page and return it. It  |                         |
+ *                    | contains exactly what   |                         |
+ *                    | we want.                | Read the block mark and |
+ *       -------------+-------------------------+ return it in a buffer   |
+ *                    | Read the conventional   | full of set bits.       |
+ *                    | OOB at the end of the   |                         |
+ *                    | page and also the block |                         |
+ *       Transcribing | mark in the metadata.   |                         |
+ *                    | Copy the block mark     |                         |
+ *                    | into the first byte of  |                         |
+ *                    | the OOB.                |                         |
+ *       -------------+-------------------------+-------------------------+
+ *
+ * Note that we break rule #4 in the Transcribing/Raw case because we're not
+ * giving an accurate view of the actual, physical bytes in the page (we're
+ * overwriting the block mark). That's OK because it's more important to follow
+ * rule #2.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ */
+static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+                               int page, int sndcmd)
+{
+       struct gpmi_nand_data *this = chip->priv;
+
+       pr_debug("page number is %d\n", page);
+       /* clear the OOB buffer */
+       memset(chip->oob_poi, ~0, mtd->oobsize);
+
+       /* Read out the conventional OOB. */
+       chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       /*
+        * Now, we want to make sure the block mark is correct. In the
+        * Swapping/Raw case, we already have it. Otherwise, we need to
+        * explicitly read it.
+        */
+       if (!this->swap_block_mark) {
+               /* Read the block mark into the first byte of the OOB buffer. */
+               chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+               chip->oob_poi[0] = chip->read_byte(mtd);
+       }
+
+       /*
+        * Return true, indicating that the next call to this function must send
+        * a command.
+        */
+       return true;
+}
+
+static int
+gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
+{
+       /*
+        * The BCH will use all the (page + oob).
+        * Our gpmi_hw_ecclayout can only prohibit the JFFS2 to write the oob.
+        * But it can not stop some ioctls such MEMWRITEOOB which uses
+        * MTD_OPS_PLACE_OOB. So We have to implement this function to prohibit
+        * these ioctls too.
+        */
+       return -EPERM;
+}
+
+static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct gpmi_nand_data *this = chip->priv;
+       int block, ret = 0;
+       uint8_t *block_mark;
+       int column, page, status, chipnr;
+
+       /* Get block number */
+       block = (int)(ofs >> chip->bbt_erase_shift);
+       if (chip->bbt)
+               chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
+
+       /* Do we have a flash based bad block table ? */
+       if (chip->options & NAND_BBT_USE_FLASH)
+               ret = nand_update_bbt(mtd, ofs);
+       else {
+               chipnr = (int)(ofs >> chip->chip_shift);
+               chip->select_chip(mtd, chipnr);
+
+               column = this->swap_block_mark ? mtd->writesize : 0;
+
+               /* Write the block mark. */
+               block_mark = this->data_buffer_dma;
+               block_mark[0] = 0; /* bad block marker */
+
+               /* Shift to get page */
+               page = (int)(ofs >> chip->page_shift);
+
+               chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page);
+               chip->write_buf(mtd, block_mark, 1);
+               chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+               status = chip->waitfunc(mtd, chip);
+               if (status & NAND_STATUS_FAIL)
+                       ret = -EIO;
+
+               chip->select_chip(mtd, -1);
+       }
+       if (!ret)
+               mtd->ecc_stats.badblocks++;
+
+       return ret;
+}
+
+static int __devinit nand_boot_set_geometry(struct gpmi_nand_data *this)
+{
+       struct boot_rom_geometry *geometry = &this->rom_geometry;
+
+       /*
+        * Set the boot block stride size.
+        *
+        * In principle, we should be reading this from the OTP bits, since
+        * that's where the ROM is going to get it. In fact, we don't have any
+        * way to read the OTP bits, so we go with the default and hope for the
+        * best.
+        */
+       geometry->stride_size_in_pages = 64;
+
+       /*
+        * Set the search area stride exponent.
+        *
+        * In principle, we should be reading this from the OTP bits, since
+        * that's where the ROM is going to get it. In fact, we don't have any
+        * way to read the OTP bits, so we go with the default and hope for the
+        * best.
+        */
+       geometry->search_area_stride_exponent = 2;
+       return 0;
+}
+
+static const char  *fingerprint = "STMP";
+static int __devinit mx23_check_transcription_stamp(struct gpmi_nand_data *this)
+{
+       struct boot_rom_geometry *rom_geo = &this->rom_geometry;
+       struct device *dev = this->dev;
+       struct mtd_info *mtd = &this->mtd;
+       struct nand_chip *chip = &this->nand;
+       unsigned int search_area_size_in_strides;
+       unsigned int stride;
+       unsigned int page;
+       loff_t byte;
+       uint8_t *buffer = chip->buffers->databuf;
+       int saved_chip_number;
+       int found_an_ncb_fingerprint = false;
+
+       /* Compute the number of strides in a search area. */
+       search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
+
+       saved_chip_number = this->current_chip;
+       chip->select_chip(mtd, 0);
+
+       /*
+        * Loop through the first search area, looking for the NCB fingerprint.
+        */
+       dev_dbg(dev, "Scanning for an NCB fingerprint...\n");
+
+       for (stride = 0; stride < search_area_size_in_strides; stride++) {
+               /* Compute the page and byte addresses. */
+               page = stride * rom_geo->stride_size_in_pages;
+               byte = page   * mtd->writesize;
+
+               dev_dbg(dev, "Looking for a fingerprint in page 0x%x\n", page);
+
+               /*
+                * Read the NCB fingerprint. The fingerprint is four bytes long
+                * and starts in the 12th byte of the page.
+                */
+               chip->cmdfunc(mtd, NAND_CMD_READ0, 12, page);
+               chip->read_buf(mtd, buffer, strlen(fingerprint));
+
+               /* Look for the fingerprint. */
+               if (!memcmp(buffer, fingerprint, strlen(fingerprint))) {
+                       found_an_ncb_fingerprint = true;
+                       break;
+               }
+
+       }
+
+       chip->select_chip(mtd, saved_chip_number);
+
+       if (found_an_ncb_fingerprint)
+               dev_dbg(dev, "\tFound a fingerprint\n");
+       else
+               dev_dbg(dev, "\tNo fingerprint found\n");
+       return found_an_ncb_fingerprint;
+}
+
+/* Writes a transcription stamp. */
+static int __devinit mx23_write_transcription_stamp(struct gpmi_nand_data *this)
+{
+       struct device *dev = this->dev;
+       struct boot_rom_geometry *rom_geo = &this->rom_geometry;
+       struct mtd_info *mtd = &this->mtd;
+       struct nand_chip *chip = &this->nand;
+       unsigned int block_size_in_pages;
+       unsigned int search_area_size_in_strides;
+       unsigned int search_area_size_in_pages;
+       unsigned int search_area_size_in_blocks;
+       unsigned int block;
+       unsigned int stride;
+       unsigned int page;
+       loff_t       byte;
+       uint8_t      *buffer = chip->buffers->databuf;
+       int saved_chip_number;
+       int status;
+
+       /* Compute the search area geometry. */
+       block_size_in_pages = mtd->erasesize / mtd->writesize;
+       search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
+       search_area_size_in_pages = search_area_size_in_strides *
+                                       rom_geo->stride_size_in_pages;
+       search_area_size_in_blocks =
+                 (search_area_size_in_pages + (block_size_in_pages - 1)) /
+                                   block_size_in_pages;
+
+       dev_dbg(dev, "Search Area Geometry :\n");
+       dev_dbg(dev, "\tin Blocks : %u\n", search_area_size_in_blocks);
+       dev_dbg(dev, "\tin Strides: %u\n", search_area_size_in_strides);
+       dev_dbg(dev, "\tin Pages  : %u\n", search_area_size_in_pages);
+
+       /* Select chip 0. */
+       saved_chip_number = this->current_chip;
+       chip->select_chip(mtd, 0);
+
+       /* Loop over blocks in the first search area, erasing them. */
+       dev_dbg(dev, "Erasing the search area...\n");
+
+       for (block = 0; block < search_area_size_in_blocks; block++) {
+               /* Compute the page address. */
+               page = block * block_size_in_pages;
+
+               /* Erase this block. */
+               dev_dbg(dev, "\tErasing block 0x%x\n", block);
+               chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+               chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
+
+               /* Wait for the erase to finish. */
+               status = chip->waitfunc(mtd, chip);
+               if (status & NAND_STATUS_FAIL)
+                       dev_err(dev, "[%s] Erase failed.\n", __func__);
+       }
+
+       /* Write the NCB fingerprint into the page buffer. */
+       memset(buffer, ~0, mtd->writesize);
+       memset(chip->oob_poi, ~0, mtd->oobsize);
+       memcpy(buffer + 12, fingerprint, strlen(fingerprint));
+
+       /* Loop through the first search area, writing NCB fingerprints. */
+       dev_dbg(dev, "Writing NCB fingerprints...\n");
+       for (stride = 0; stride < search_area_size_in_strides; stride++) {
+               /* Compute the page and byte addresses. */
+               page = stride * rom_geo->stride_size_in_pages;
+               byte = page   * mtd->writesize;
+
+               /* Write the first page of the current stride. */
+               dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
+               chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+               chip->ecc.write_page_raw(mtd, chip, buffer);
+               chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+               /* Wait for the write to finish. */
+               status = chip->waitfunc(mtd, chip);
+               if (status & NAND_STATUS_FAIL)
+                       dev_err(dev, "[%s] Write failed.\n", __func__);
+       }
+
+       /* Deselect chip 0. */
+       chip->select_chip(mtd, saved_chip_number);
+       return 0;
+}
+
+static int __devinit mx23_boot_init(struct gpmi_nand_data  *this)
+{
+       struct device *dev = this->dev;
+       struct nand_chip *chip = &this->nand;
+       struct mtd_info *mtd = &this->mtd;
+       unsigned int block_count;
+       unsigned int block;
+       int     chipnr;
+       int     page;
+       loff_t  byte;
+       uint8_t block_mark;
+       int     ret = 0;
+
+       /*
+        * If control arrives here, we can't use block mark swapping, which
+        * means we're forced to use transcription. First, scan for the
+        * transcription stamp. If we find it, then we don't have to do
+        * anything -- the block marks are already transcribed.
+        */
+       if (mx23_check_transcription_stamp(this))
+               return 0;
+
+       /*
+        * If control arrives here, we couldn't find a transcription stamp, so
+        * so we presume the block marks are in the conventional location.
+        */
+       dev_dbg(dev, "Transcribing bad block marks...\n");
+
+       /* Compute the number of blocks in the entire medium. */
+       block_count = chip->chipsize >> chip->phys_erase_shift;
+
+       /*
+        * Loop over all the blocks in the medium, transcribing block marks as
+        * we go.
+        */
+       for (block = 0; block < block_count; block++) {
+               /*
+                * Compute the chip, page and byte addresses for this block's
+                * conventional mark.
+                */
+               chipnr = block >> (chip->chip_shift - chip->phys_erase_shift);
+               page = block << (chip->phys_erase_shift - chip->page_shift);
+               byte = block <<  chip->phys_erase_shift;
+
+               /* Send the command to read the conventional block mark. */
+               chip->select_chip(mtd, chipnr);
+               chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+               block_mark = chip->read_byte(mtd);
+               chip->select_chip(mtd, -1);
+
+               /*
+                * Check if the block is marked bad. If so, we need to mark it
+                * again, but this time the result will be a mark in the
+                * location where we transcribe block marks.
+                */
+               if (block_mark != 0xff) {
+                       dev_dbg(dev, "Transcribing mark in block %u\n", block);
+                       ret = chip->block_markbad(mtd, byte);
+                       if (ret)
+                               dev_err(dev, "Failed to mark block bad with "
+                                                       "ret %d\n", ret);
+               }
+       }
+
+       /* Write the stamp that indicates we've transcribed the block marks. */
+       mx23_write_transcription_stamp(this);
+       return 0;
+}
+
+static int __devinit nand_boot_init(struct gpmi_nand_data  *this)
+{
+       nand_boot_set_geometry(this);
+
+       /* This is ROM arch-specific initilization before the BBT scanning. */
+       if (GPMI_IS_MX23(this))
+               return mx23_boot_init(this);
+       return 0;
+}
+
+static int __devinit gpmi_set_geometry(struct gpmi_nand_data *this)
+{
+       int ret;
+
+       /* Free the temporary DMA memory for reading ID. */
+       gpmi_free_dma_buffer(this);
+
+       /* Set up the NFC geometry which is used by BCH. */
+       ret = bch_set_geometry(this);
+       if (ret) {
+               pr_err("set geometry ret : %d\n", ret);
+               return ret;
+       }
+
+       /* Alloc the new DMA buffers according to the pagesize and oobsize */
+       return gpmi_alloc_dma_buffer(this);
+}
+
+static int gpmi_pre_bbt_scan(struct gpmi_nand_data  *this)
+{
+       int ret;
+
+       /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
+       if (GPMI_IS_MX23(this))
+               this->swap_block_mark = false;
+       else
+               this->swap_block_mark = true;
+
+       /* Set up the medium geometry */
+       ret = gpmi_set_geometry(this);
+       if (ret)
+               return ret;
+
+       /* NAND boot init, depends on the gpmi_set_geometry(). */
+       return nand_boot_init(this);
+}
+
+static int gpmi_scan_bbt(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd->priv;
+       struct gpmi_nand_data *this = chip->priv;
+       int ret;
+
+       /* Prepare for the BBT scan. */
+       ret = gpmi_pre_bbt_scan(this);
+       if (ret)
+               return ret;
+
+       /* use the default BBT implementation */
+       return nand_default_bbt(mtd);
+}
+
+void gpmi_nfc_exit(struct gpmi_nand_data *this)
+{
+       nand_release(&this->mtd);
+       gpmi_free_dma_buffer(this);
+}
+
+static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
+{
+       struct gpmi_nand_platform_data *pdata = this->pdata;
+       struct mtd_info  *mtd = &this->mtd;
+       struct nand_chip *chip = &this->nand;
+       int ret;
+
+       /* init current chip */
+       this->current_chip      = -1;
+
+       /* init the MTD data structures */
+       mtd->priv               = chip;
+       mtd->name               = "gpmi-nand";
+       mtd->owner              = THIS_MODULE;
+
+       /* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */
+       chip->priv              = this;
+       chip->select_chip       = gpmi_select_chip;
+       chip->cmd_ctrl          = gpmi_cmd_ctrl;
+       chip->dev_ready         = gpmi_dev_ready;
+       chip->read_byte         = gpmi_read_byte;
+       chip->read_buf          = gpmi_read_buf;
+       chip->write_buf         = gpmi_write_buf;
+       chip->ecc.read_page     = gpmi_ecc_read_page;
+       chip->ecc.write_page    = gpmi_ecc_write_page;
+       chip->ecc.read_oob      = gpmi_ecc_read_oob;
+       chip->ecc.write_oob     = gpmi_ecc_write_oob;
+       chip->scan_bbt          = gpmi_scan_bbt;
+       chip->badblock_pattern  = &gpmi_bbt_descr;
+       chip->block_markbad     = gpmi_block_markbad;
+       chip->options           |= NAND_NO_SUBPAGE_WRITE;
+       chip->ecc.mode          = NAND_ECC_HW;
+       chip->ecc.size          = 1;
+       chip->ecc.layout        = &gpmi_hw_ecclayout;
+
+       /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */
+       this->bch_geometry.payload_size = 1024;
+       this->bch_geometry.auxiliary_size = 128;
+       ret = gpmi_alloc_dma_buffer(this);
+       if (ret)
+               goto err_out;
+
+       ret = nand_scan(mtd, pdata->max_chip_count);
+       if (ret) {
+               pr_err("Chip scan failed\n");
+               goto err_out;
+       }
+
+       ret = mtd_device_parse_register(mtd, NULL, NULL,
+                       pdata->partitions, pdata->partition_count);
+       if (ret)
+               goto err_out;
+       return 0;
+
+err_out:
+       gpmi_nfc_exit(this);
+       return ret;
+}
+
+static int __devinit gpmi_nand_probe(struct platform_device *pdev)
+{
+       struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data;
+       struct gpmi_nand_data *this;
+       int ret;
+
+       this = kzalloc(sizeof(*this), GFP_KERNEL);
+       if (!this) {
+               pr_err("Failed to allocate per-device memory\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, this);
+       this->pdev  = pdev;
+       this->dev   = &pdev->dev;
+       this->pdata = pdata;
+
+       if (pdata->platform_init) {
+               ret = pdata->platform_init();
+               if (ret)
+                       goto platform_init_error;
+       }
+
+       ret = acquire_resources(this);
+       if (ret)
+               goto exit_acquire_resources;
+
+       ret = init_hardware(this);
+       if (ret)
+               goto exit_nfc_init;
+
+       ret = gpmi_nfc_init(this);
+       if (ret)
+               goto exit_nfc_init;
+
+       return 0;
+
+exit_nfc_init:
+       release_resources(this);
+platform_init_error:
+exit_acquire_resources:
+       platform_set_drvdata(pdev, NULL);
+       kfree(this);
+       return ret;
+}
+
+static int __exit gpmi_nand_remove(struct platform_device *pdev)
+{
+       struct gpmi_nand_data *this = platform_get_drvdata(pdev);
+
+       gpmi_nfc_exit(this);
+       release_resources(this);
+       platform_set_drvdata(pdev, NULL);
+       kfree(this);
+       return 0;
+}
+
+static const struct platform_device_id gpmi_ids[] = {
+       {
+               .name = "imx23-gpmi-nand",
+               .driver_data = IS_MX23,
+       }, {
+               .name = "imx28-gpmi-nand",
+               .driver_data = IS_MX28,
+       }, {},
+};
+
+static struct platform_driver gpmi_nand_driver = {
+       .driver = {
+               .name = "gpmi-nand",
+       },
+       .probe   = gpmi_nand_probe,
+       .remove  = __exit_p(gpmi_nand_remove),
+       .id_table = gpmi_ids,
+};
+
+static int __init gpmi_nand_init(void)
+{
+       int err;
+
+       err = platform_driver_register(&gpmi_nand_driver);
+       if (err == 0)
+               printk(KERN_INFO "GPMI NAND driver registered. (IMX)\n");
+       else
+               pr_err("i.MX GPMI NAND driver registration failed\n");
+       return err;
+}
+
+static void __exit gpmi_nand_exit(void)
+{
+       platform_driver_unregister(&gpmi_nand_driver);
+}
+
+module_init(gpmi_nand_init);
+module_exit(gpmi_nand_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX GPMI NAND Flash Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
new file mode 100644 (file)
index 0000000..e023bcc
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __DRIVERS_MTD_NAND_GPMI_NAND_H
+#define __DRIVERS_MTD_NAND_GPMI_NAND_H
+
+#include <linux/mtd/nand.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <mach/dma.h>
+
+struct resources {
+       void          *gpmi_regs;
+       void          *bch_regs;
+       unsigned int  bch_low_interrupt;
+       unsigned int  bch_high_interrupt;
+       unsigned int  dma_low_channel;
+       unsigned int  dma_high_channel;
+       struct clk    *clock;
+};
+
+/**
+ * struct bch_geometry - BCH geometry description.
+ * @gf_len:                   The length of Galois Field. (e.g., 13 or 14)
+ * @ecc_strength:             A number that describes the strength of the ECC
+ *                            algorithm.
+ * @page_size:                The size, in bytes, of a physical page, including
+ *                            both data and OOB.
+ * @metadata_size:            The size, in bytes, of the metadata.
+ * @ecc_chunk_size:           The size, in bytes, of a single ECC chunk. Note
+ *                            the first chunk in the page includes both data and
+ *                            metadata, so it's a bit larger than this value.
+ * @ecc_chunk_count:          The number of ECC chunks in the page,
+ * @payload_size:             The size, in bytes, of the payload buffer.
+ * @auxiliary_size:           The size, in bytes, of the auxiliary buffer.
+ * @auxiliary_status_offset:  The offset into the auxiliary buffer at which
+ *                            the ECC status appears.
+ * @block_mark_byte_offset:   The byte offset in the ECC-based page view at
+ *                            which the underlying physical block mark appears.
+ * @block_mark_bit_offset:    The bit offset into the ECC-based page view at
+ *                            which the underlying physical block mark appears.
+ */
+struct bch_geometry {
+       unsigned int  gf_len;
+       unsigned int  ecc_strength;
+       unsigned int  page_size;
+       unsigned int  metadata_size;
+       unsigned int  ecc_chunk_size;
+       unsigned int  ecc_chunk_count;
+       unsigned int  payload_size;
+       unsigned int  auxiliary_size;
+       unsigned int  auxiliary_status_offset;
+       unsigned int  block_mark_byte_offset;
+       unsigned int  block_mark_bit_offset;
+};
+
+/**
+ * struct boot_rom_geometry - Boot ROM geometry description.
+ * @stride_size_in_pages:        The size of a boot block stride, in pages.
+ * @search_area_stride_exponent: The logarithm to base 2 of the size of a
+ *                               search area in boot block strides.
+ */
+struct boot_rom_geometry {
+       unsigned int  stride_size_in_pages;
+       unsigned int  search_area_stride_exponent;
+};
+
+/* DMA operations types */
+enum dma_ops_type {
+       DMA_FOR_COMMAND = 1,
+       DMA_FOR_READ_DATA,
+       DMA_FOR_WRITE_DATA,
+       DMA_FOR_READ_ECC_PAGE,
+       DMA_FOR_WRITE_ECC_PAGE
+};
+
+/**
+ * struct nand_timing - Fundamental timing attributes for NAND.
+ * @data_setup_in_ns:         The data setup time, in nanoseconds. Usually the
+ *                            maximum of tDS and tWP. A negative value
+ *                            indicates this characteristic isn't known.
+ * @data_hold_in_ns:          The data hold time, in nanoseconds. Usually the
+ *                            maximum of tDH, tWH and tREH. A negative value
+ *                            indicates this characteristic isn't known.
+ * @address_setup_in_ns:      The address setup time, in nanoseconds. Usually
+ *                            the maximum of tCLS, tCS and tALS. A negative
+ *                            value indicates this characteristic isn't known.
+ * @gpmi_sample_delay_in_ns:  A GPMI-specific timing parameter. A negative value
+ *                            indicates this characteristic isn't known.
+ * @tREA_in_ns:               tREA, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ * @tRLOH_in_ns:              tRLOH, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ * @tRHOH_in_ns:              tRHOH, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ */
+struct nand_timing {
+       int8_t  data_setup_in_ns;
+       int8_t  data_hold_in_ns;
+       int8_t  address_setup_in_ns;
+       int8_t  gpmi_sample_delay_in_ns;
+       int8_t  tREA_in_ns;
+       int8_t  tRLOH_in_ns;
+       int8_t  tRHOH_in_ns;
+};
+
+struct gpmi_nand_data {
+       /* System Interface */
+       struct device           *dev;
+       struct platform_device  *pdev;
+       struct gpmi_nand_platform_data  *pdata;
+
+       /* Resources */
+       struct resources        resources;
+
+       /* Flash Hardware */
+       struct nand_timing      timing;
+
+       /* BCH */
+       struct bch_geometry     bch_geometry;
+       struct completion       bch_done;
+
+       /* NAND Boot issue */
+       bool                    swap_block_mark;
+       struct boot_rom_geometry rom_geometry;
+
+       /* MTD / NAND */
+       struct nand_chip        nand;
+       struct mtd_info         mtd;
+
+       /* General-use Variables */
+       int                     current_chip;
+       unsigned int            command_length;
+
+       /* passed from upper layer */
+       uint8_t                 *upper_buf;
+       int                     upper_len;
+
+       /* for DMA operations */
+       bool                    direct_dma_map_ok;
+
+       struct scatterlist      cmd_sgl;
+       char                    *cmd_buffer;
+
+       struct scatterlist      data_sgl;
+       char                    *data_buffer_dma;
+
+       void                    *page_buffer_virt;
+       dma_addr_t              page_buffer_phys;
+       unsigned int            page_buffer_size;
+
+       void                    *payload_virt;
+       dma_addr_t              payload_phys;
+
+       void                    *auxiliary_virt;
+       dma_addr_t              auxiliary_phys;
+
+       /* DMA channels */
+#define DMA_CHANS              8
+       struct dma_chan         *dma_chans[DMA_CHANS];
+       struct mxs_dma_data     dma_data;
+       enum dma_ops_type       last_dma_type;
+       enum dma_ops_type       dma_type;
+       struct completion       dma_done;
+
+       /* private */
+       void                    *private;
+};
+
+/**
+ * struct gpmi_nfc_hardware_timing - GPMI hardware timing parameters.
+ * @data_setup_in_cycles:      The data setup time, in cycles.
+ * @data_hold_in_cycles:       The data hold time, in cycles.
+ * @address_setup_in_cycles:   The address setup time, in cycles.
+ * @use_half_periods:          Indicates the clock is running slowly, so the
+ *                             NFC DLL should use half-periods.
+ * @sample_delay_factor:       The sample delay factor.
+ */
+struct gpmi_nfc_hardware_timing {
+       uint8_t  data_setup_in_cycles;
+       uint8_t  data_hold_in_cycles;
+       uint8_t  address_setup_in_cycles;
+       bool     use_half_periods;
+       uint8_t  sample_delay_factor;
+};
+
+/**
+ * struct timing_threshod - Timing threshold
+ * @max_data_setup_cycles:       The maximum number of data setup cycles that
+ *                               can be expressed in the hardware.
+ * @internal_data_setup_in_ns:   The time, in ns, that the NFC hardware requires
+ *                               for data read internal setup. In the Reference
+ *                               Manual, see the chapter "High-Speed NAND
+ *                               Timing" for more details.
+ * @max_sample_delay_factor:     The maximum sample delay factor that can be
+ *                               expressed in the hardware.
+ * @max_dll_clock_period_in_ns:  The maximum period of the GPMI clock that the
+ *                               sample delay DLL hardware can possibly work
+ *                               with (the DLL is unusable with longer periods).
+ *                               If the full-cycle period is greater than HALF
+ *                               this value, the DLL must be configured to use
+ *                               half-periods.
+ * @max_dll_delay_in_ns:         The maximum amount of delay, in ns, that the
+ *                               DLL can implement.
+ * @clock_frequency_in_hz:       The clock frequency, in Hz, during the current
+ *                               I/O transaction. If no I/O transaction is in
+ *                               progress, this is the clock frequency during
+ *                               the most recent I/O transaction.
+ */
+struct timing_threshod {
+       const unsigned int      max_chip_count;
+       const unsigned int      max_data_setup_cycles;
+       const unsigned int      internal_data_setup_in_ns;
+       const unsigned int      max_sample_delay_factor;
+       const unsigned int      max_dll_clock_period_in_ns;
+       const unsigned int      max_dll_delay_in_ns;
+       unsigned long           clock_frequency_in_hz;
+
+};
+
+/* Common Services */
+extern int common_nfc_set_geometry(struct gpmi_nand_data *);
+extern struct dma_chan *get_dma_chan(struct gpmi_nand_data *);
+extern void prepare_data_dma(struct gpmi_nand_data *,
+                               enum dma_data_direction dr);
+extern int start_dma_without_bch_irq(struct gpmi_nand_data *,
+                               struct dma_async_tx_descriptor *);
+extern int start_dma_with_bch_irq(struct gpmi_nand_data *,
+                               struct dma_async_tx_descriptor *);
+
+/* GPMI-NAND helper function library */
+extern int gpmi_init(struct gpmi_nand_data *);
+extern void gpmi_clear_bch(struct gpmi_nand_data *);
+extern void gpmi_dump_info(struct gpmi_nand_data *);
+extern int bch_set_geometry(struct gpmi_nand_data *);
+extern int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip);
+extern int gpmi_send_command(struct gpmi_nand_data *);
+extern void gpmi_begin(struct gpmi_nand_data *);
+extern void gpmi_end(struct gpmi_nand_data *);
+extern int gpmi_read_data(struct gpmi_nand_data *);
+extern int gpmi_send_data(struct gpmi_nand_data *);
+extern int gpmi_send_page(struct gpmi_nand_data *,
+                       dma_addr_t payload, dma_addr_t auxiliary);
+extern int gpmi_read_page(struct gpmi_nand_data *,
+                       dma_addr_t payload, dma_addr_t auxiliary);
+
+/* BCH : Status Block Completion Codes */
+#define STATUS_GOOD            0x00
+#define STATUS_ERASED          0xff
+#define STATUS_UNCORRECTABLE   0xfe
+
+/* Use the platform_id to distinguish different Archs. */
+#define IS_MX23                        0x1
+#define IS_MX28                        0x2
+#define GPMI_IS_MX23(x)                ((x)->pdev->id_entry->driver_data == IS_MX23)
+#define GPMI_IS_MX28(x)                ((x)->pdev->id_entry->driver_data == IS_MX28)
+#endif
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h b/drivers/mtd/nand/gpmi-nand/gpmi-regs.h
new file mode 100644 (file)
index 0000000..8343124
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __GPMI_NAND_GPMI_REGS_H
+#define __GPMI_NAND_GPMI_REGS_H
+
+#define HW_GPMI_CTRL0                                  0x00000000
+#define HW_GPMI_CTRL0_SET                              0x00000004
+#define HW_GPMI_CTRL0_CLR                              0x00000008
+#define HW_GPMI_CTRL0_TOG                              0x0000000c
+
+#define BP_GPMI_CTRL0_COMMAND_MODE                     24
+#define BM_GPMI_CTRL0_COMMAND_MODE     (3 << BP_GPMI_CTRL0_COMMAND_MODE)
+#define BF_GPMI_CTRL0_COMMAND_MODE(v)  \
+       (((v) << BP_GPMI_CTRL0_COMMAND_MODE) & BM_GPMI_CTRL0_COMMAND_MODE)
+#define BV_GPMI_CTRL0_COMMAND_MODE__WRITE              0x0
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ               0x1
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ_AND_COMPARE   0x2
+#define BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY     0x3
+
+#define BM_GPMI_CTRL0_WORD_LENGTH                      (1 << 23)
+#define BV_GPMI_CTRL0_WORD_LENGTH__16_BIT              0x0
+#define BV_GPMI_CTRL0_WORD_LENGTH__8_BIT               0x1
+
+/*
+ *  Difference in LOCK_CS between imx23 and imx28 :
+ *  This bit may impact the _POWER_ consumption. So some chips
+ *  do not set it.
+ */
+#define MX23_BP_GPMI_CTRL0_LOCK_CS                     22
+#define MX28_BP_GPMI_CTRL0_LOCK_CS                     27
+#define LOCK_CS_ENABLE                                 0x1
+#define BF_GPMI_CTRL0_LOCK_CS(v, x)                    0x0
+
+/* Difference in CS between imx23 and imx28 */
+#define BP_GPMI_CTRL0_CS                               20
+#define MX23_BM_GPMI_CTRL0_CS          (3 << BP_GPMI_CTRL0_CS)
+#define MX28_BM_GPMI_CTRL0_CS          (7 << BP_GPMI_CTRL0_CS)
+#define BF_GPMI_CTRL0_CS(v, x)         (((v) << BP_GPMI_CTRL0_CS) & \
+                                               (GPMI_IS_MX23((x)) \
+                                               ? MX23_BM_GPMI_CTRL0_CS \
+                                               : MX28_BM_GPMI_CTRL0_CS))
+
+#define BP_GPMI_CTRL0_ADDRESS                          17
+#define BM_GPMI_CTRL0_ADDRESS          (3 << BP_GPMI_CTRL0_ADDRESS)
+#define BF_GPMI_CTRL0_ADDRESS(v)       \
+               (((v) << BP_GPMI_CTRL0_ADDRESS) & BM_GPMI_CTRL0_ADDRESS)
+#define BV_GPMI_CTRL0_ADDRESS__NAND_DATA               0x0
+#define BV_GPMI_CTRL0_ADDRESS__NAND_CLE                        0x1
+#define BV_GPMI_CTRL0_ADDRESS__NAND_ALE                        0x2
+
+#define BM_GPMI_CTRL0_ADDRESS_INCREMENT                        (1 << 16)
+#define BV_GPMI_CTRL0_ADDRESS_INCREMENT__DISABLED      0x0
+#define BV_GPMI_CTRL0_ADDRESS_INCREMENT__ENABLED       0x1
+
+#define BP_GPMI_CTRL0_XFER_COUNT                       0
+#define BM_GPMI_CTRL0_XFER_COUNT       (0xffff << BP_GPMI_CTRL0_XFER_COUNT)
+#define BF_GPMI_CTRL0_XFER_COUNT(v)    \
+               (((v) << BP_GPMI_CTRL0_XFER_COUNT) & BM_GPMI_CTRL0_XFER_COUNT)
+
+#define HW_GPMI_COMPARE                                        0x00000010
+
+#define HW_GPMI_ECCCTRL                                        0x00000020
+#define HW_GPMI_ECCCTRL_SET                            0x00000024
+#define HW_GPMI_ECCCTRL_CLR                            0x00000028
+#define HW_GPMI_ECCCTRL_TOG                            0x0000002c
+
+#define BP_GPMI_ECCCTRL_ECC_CMD                                13
+#define BM_GPMI_ECCCTRL_ECC_CMD                (3 << BP_GPMI_ECCCTRL_ECC_CMD)
+#define BF_GPMI_ECCCTRL_ECC_CMD(v)     \
+               (((v) << BP_GPMI_ECCCTRL_ECC_CMD) & BM_GPMI_ECCCTRL_ECC_CMD)
+#define BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE            0x0
+#define BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE            0x1
+
+#define BM_GPMI_ECCCTRL_ENABLE_ECC                     (1 << 12)
+#define BV_GPMI_ECCCTRL_ENABLE_ECC__ENABLE             0x1
+#define BV_GPMI_ECCCTRL_ENABLE_ECC__DISABLE            0x0
+
+#define BP_GPMI_ECCCTRL_BUFFER_MASK                    0
+#define BM_GPMI_ECCCTRL_BUFFER_MASK    (0x1ff << BP_GPMI_ECCCTRL_BUFFER_MASK)
+#define BF_GPMI_ECCCTRL_BUFFER_MASK(v) \
+       (((v) << BP_GPMI_ECCCTRL_BUFFER_MASK) & BM_GPMI_ECCCTRL_BUFFER_MASK)
+#define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY       0x100
+#define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE          0x1FF
+
+#define HW_GPMI_ECCCOUNT                               0x00000030
+#define HW_GPMI_PAYLOAD                                        0x00000040
+#define HW_GPMI_AUXILIARY                              0x00000050
+#define HW_GPMI_CTRL1                                  0x00000060
+#define HW_GPMI_CTRL1_SET                              0x00000064
+#define HW_GPMI_CTRL1_CLR                              0x00000068
+#define HW_GPMI_CTRL1_TOG                              0x0000006c
+
+#define BM_GPMI_CTRL1_BCH_MODE                         (1 << 18)
+
+#define BP_GPMI_CTRL1_DLL_ENABLE                       17
+#define BM_GPMI_CTRL1_DLL_ENABLE       (1 << BP_GPMI_CTRL1_DLL_ENABLE)
+
+#define BP_GPMI_CTRL1_HALF_PERIOD                      16
+#define BM_GPMI_CTRL1_HALF_PERIOD      (1 << BP_GPMI_CTRL1_HALF_PERIOD)
+
+#define BP_GPMI_CTRL1_RDN_DELAY                                12
+#define BM_GPMI_CTRL1_RDN_DELAY                (0xf << BP_GPMI_CTRL1_RDN_DELAY)
+#define BF_GPMI_CTRL1_RDN_DELAY(v)     \
+               (((v) << BP_GPMI_CTRL1_RDN_DELAY) & BM_GPMI_CTRL1_RDN_DELAY)
+
+#define BM_GPMI_CTRL1_DEV_RESET                                (1 << 3)
+#define BV_GPMI_CTRL1_DEV_RESET__ENABLED               0x0
+#define BV_GPMI_CTRL1_DEV_RESET__DISABLED              0x1
+
+#define BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY              (1 << 2)
+#define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVELOW   0x0
+#define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVEHIGH  0x1
+
+#define BM_GPMI_CTRL1_CAMERA_MODE                      (1 << 1)
+#define BV_GPMI_CTRL1_GPMI_MODE__NAND                  0x0
+#define BV_GPMI_CTRL1_GPMI_MODE__ATA                   0x1
+
+#define BM_GPMI_CTRL1_GPMI_MODE                                (1 << 0)
+
+#define HW_GPMI_TIMING0                                        0x00000070
+
+#define BP_GPMI_TIMING0_ADDRESS_SETUP                  16
+#define BM_GPMI_TIMING0_ADDRESS_SETUP  (0xff << BP_GPMI_TIMING0_ADDRESS_SETUP)
+#define BF_GPMI_TIMING0_ADDRESS_SETUP(v)       \
+       (((v) << BP_GPMI_TIMING0_ADDRESS_SETUP) & BM_GPMI_TIMING0_ADDRESS_SETUP)
+
+#define BP_GPMI_TIMING0_DATA_HOLD                      8
+#define BM_GPMI_TIMING0_DATA_HOLD      (0xff << BP_GPMI_TIMING0_DATA_HOLD)
+#define BF_GPMI_TIMING0_DATA_HOLD(v)           \
+       (((v) << BP_GPMI_TIMING0_DATA_HOLD) & BM_GPMI_TIMING0_DATA_HOLD)
+
+#define BP_GPMI_TIMING0_DATA_SETUP                     0
+#define BM_GPMI_TIMING0_DATA_SETUP     (0xff << BP_GPMI_TIMING0_DATA_SETUP)
+#define BF_GPMI_TIMING0_DATA_SETUP(v)          \
+       (((v) << BP_GPMI_TIMING0_DATA_SETUP) & BM_GPMI_TIMING0_DATA_SETUP)
+
+#define HW_GPMI_TIMING1                                        0x00000080
+#define BP_GPMI_TIMING1_BUSY_TIMEOUT                   16
+
+#define HW_GPMI_TIMING2                                        0x00000090
+#define HW_GPMI_DATA                                   0x000000a0
+
+/* MX28 uses this to detect READY. */
+#define HW_GPMI_STAT                                   0x000000b0
+#define MX28_BP_GPMI_STAT_READY_BUSY                   24
+#define MX28_BM_GPMI_STAT_READY_BUSY   (0xff << MX28_BP_GPMI_STAT_READY_BUSY)
+#define MX28_BF_GPMI_STAT_READY_BUSY(v)                \
+       (((v) << MX28_BP_GPMI_STAT_READY_BUSY) & MX28_BM_GPMI_STAT_READY_BUSY)
+
+/* MX23 uses this to detect READY. */
+#define HW_GPMI_DEBUG                                  0x000000c0
+#define MX23_BP_GPMI_DEBUG_READY0                      28
+#define MX23_BM_GPMI_DEBUG_READY0      (1 << MX23_BP_GPMI_DEBUG_READY0)
+#endif
index 02a03e67109c90ce2534757b4053ada8e8469956..5dc6f0d92f1af7be563fd269b70ee505b0a08b9c 100644 (file)
@@ -81,9 +81,6 @@ static int h1910_device_ready(struct mtd_info *mtd)
 static int __init h1910_init(void)
 {
        struct nand_chip *this;
-       const char *part_type = 0;
-       int mtd_parts_nb = 0;
-       struct mtd_partition *mtd_parts = 0;
        void __iomem *nandaddr;
 
        if (!machine_is_h1900())
@@ -136,22 +133,10 @@ static int __init h1910_init(void)
                iounmap((void *)nandaddr);
                return -ENXIO;
        }
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-       mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand");
-       if (mtd_parts_nb > 0)
-               part_type = "command line";
-       else
-               mtd_parts_nb = 0;
-#endif
-       if (mtd_parts_nb == 0) {
-               mtd_parts = partition_info;
-               mtd_parts_nb = NUM_PARTITIONS;
-               part_type = "static";
-       }
 
        /* Register the partitions */
-       printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-       mtd_device_register(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
+       mtd_device_parse_register(h1910_nand_mtd, NULL, 0,
+                       partition_info, NUM_PARTITIONS);
 
        /* Return happy */
        return 0;
index 6e813daed068d359f66f3c2ffb65abf46d924a44..e2664073a89b8eae1afa5c2ef5fe3d81e0348722 100644 (file)
@@ -251,10 +251,6 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
        return 0;
 }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = {"cmdline", NULL};
-#endif
-
 static int jz_nand_ioremap_resource(struct platform_device *pdev,
        const char *name, struct resource **res, void __iomem **base)
 {
@@ -299,8 +295,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
        struct nand_chip *chip;
        struct mtd_info *mtd;
        struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
-       struct mtd_partition *partition_info;
-       int num_partitions = 0;
 
        nand = kzalloc(sizeof(*nand), GFP_KERNEL);
        if (!nand) {
@@ -373,15 +367,9 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
                goto err_gpio_free;
        }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-       num_partitions = parse_mtd_partitions(mtd, part_probes,
-                                               &partition_info, 0);
-#endif
-       if (num_partitions <= 0 && pdata) {
-               num_partitions = pdata->num_partitions;
-               partition_info = pdata->partitions;
-       }
-       ret = mtd_device_register(mtd, partition_info, num_partitions);
+       ret = mtd_device_parse_register(mtd, NULL, 0,
+                       pdata ? pdata->partitions : NULL,
+                       pdata ? pdata->num_partitions : 0);
 
        if (ret) {
                dev_err(&pdev->dev, "Failed to add mtd device\n");
index eb1fbac63eb6015ce2804d7e676698c4b51cd3ed..5ede64706346084dd5cdd6d38612d532ec493992 100644 (file)
@@ -131,8 +131,6 @@ struct mpc5121_nfc_prv {
 
 static void mpc5121_nfc_done(struct mtd_info *mtd);
 
-static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL };
-
 /* Read NFC register */
 static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
 {
@@ -656,13 +654,13 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
        struct mpc5121_nfc_prv *prv;
        struct resource res;
        struct mtd_info *mtd;
-       struct mtd_partition *parts;
        struct nand_chip *chip;
        unsigned long regs_paddr, regs_size;
        const __be32 *chips_no;
        int resettime = 0;
        int retval = 0;
        int rev, len;
+       struct mtd_part_parser_data ppdata;
 
        /*
         * Check SoC revision. This driver supports only NFC
@@ -727,6 +725,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
        }
 
        mtd->name = "MPC5121 NAND";
+       ppdata.of_node = dn;
        chip->dev_ready = mpc5121_nfc_dev_ready;
        chip->cmdfunc = mpc5121_nfc_command;
        chip->read_byte = mpc5121_nfc_read_byte;
@@ -735,7 +734,8 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
        chip->write_buf = mpc5121_nfc_write_buf;
        chip->verify_buf = mpc5121_nfc_verify_buf;
        chip->select_chip = mpc5121_nfc_select_chip;
-       chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT;
+       chip->options = NAND_NO_AUTOINCR;
+       chip->bbt_options = NAND_BBT_USE_FLASH;
        chip->ecc.mode = NAND_ECC_SOFT;
 
        /* Support external chip-select logic on ADS5121 board */
@@ -837,19 +837,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
        dev_set_drvdata(dev, mtd);
 
        /* Register device in MTD */
-       retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0);
-#ifdef CONFIG_MTD_OF_PARTS
-       if (retval == 0)
-               retval = of_mtd_parse_partitions(dev, dn, &parts);
-#endif
-       if (retval < 0) {
-               dev_err(dev, "Error parsing MTD partitions!\n");
-               devm_free_irq(dev, prv->irq, mtd);
-               retval = -EINVAL;
-               goto error;
-       }
-
-       retval = mtd_device_register(mtd, parts, retval);
+       retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
        if (retval) {
                dev_err(dev, "Error adding MTD device!\n");
                devm_free_irq(dev, prv->irq, mtd);
index 90df34c4d26cae887454de88099fa6c672c6b88d..74a43b818d0e0401616dcc5ace7af52bcf53c726 100644 (file)
@@ -41,7 +41,7 @@
 
 #define nfc_is_v21()           (cpu_is_mx25() || cpu_is_mx35())
 #define nfc_is_v1()            (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
-#define nfc_is_v3_2()          cpu_is_mx51()
+#define nfc_is_v3_2()          (cpu_is_mx51() || cpu_is_mx53())
 #define nfc_is_v3()            nfc_is_v3_2()
 
 /* Addresses for NFC registers */
 struct mxc_nand_host {
        struct mtd_info         mtd;
        struct nand_chip        nand;
-       struct mtd_partition    *parts;
        struct device           *dev;
 
        void                    *spare0;
@@ -350,8 +349,7 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
                        udelay(1);
                }
                if (max_retries < 0)
-                       DEBUG(MTD_DEBUG_LEVEL0, "%s: INT not set\n",
-                             __func__);
+                       pr_debug("%s: INT not set\n", __func__);
        }
 }
 
@@ -371,7 +369,7 @@ static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
  * waits for completion. */
 static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
 {
-       DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
+       pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
 
        writew(cmd, NFC_V1_V2_FLASH_CMD);
        writew(NFC_CMD, NFC_V1_V2_CONFIG2);
@@ -387,8 +385,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
                        udelay(1);
                }
                if (max_retries < 0)
-                       DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n",
-                             __func__);
+                       pr_debug("%s: RESET failed\n", __func__);
        } else {
                /* Wait for operation to complete */
                wait_op_done(host, useirq);
@@ -411,7 +408,7 @@ static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
  * a NAND command. */
 static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
 {
-       DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
+       pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
 
        writew(addr, NFC_V1_V2_FLASH_ADDR);
        writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
@@ -561,8 +558,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
        uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT);
 
        if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
-               DEBUG(MTD_DEBUG_LEVEL0,
-                     "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+               pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
                return -1;
        }
 
@@ -849,7 +845,7 @@ static void preset_v1_v2(struct mtd_info *mtd)
                writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
        } else if (nfc_is_v1()) {
                writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
-               writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
+               writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
        } else
                BUG();
 
@@ -932,8 +928,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
        struct nand_chip *nand_chip = mtd->priv;
        struct mxc_nand_host *host = nand_chip->priv;
 
-       DEBUG(MTD_DEBUG_LEVEL3,
-             "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+       pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
              command, column, page_addr);
 
        /* Reset command state information */
@@ -1044,7 +1039,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
        struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
        struct mxc_nand_host *host;
        struct resource *res;
-       int err = 0, __maybe_unused nr_parts = 0;
+       int err = 0;
        struct nand_ecclayout *oob_smallpage, *oob_largepage;
 
        /* Allocate memory for MTD device structure and private data */
@@ -1179,7 +1174,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
                this->bbt_td = &bbt_main_descr;
                this->bbt_md = &bbt_mirror_descr;
                /* update flash based bbt */
-               this->options |= NAND_USE_FLASH_BBT;
+               this->bbt_options |= NAND_BBT_USE_FLASH;
        }
 
        init_completion(&host->op_completion);
@@ -1231,16 +1226,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
        }
 
        /* Register the partitions */
-       nr_parts =
-           parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
-       if (nr_parts > 0)
-               mtd_device_register(mtd, host->parts, nr_parts);
-       else if (pdata->parts)
-               mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
-       else {
-               pr_info("Registering %s as whole device\n", mtd->name);
-               mtd_device_register(mtd, NULL, 0);
-       }
+       mtd_device_parse_register(mtd, part_probes, 0,
+                       pdata->parts, pdata->nr_parts);
 
        platform_set_drvdata(pdev, host);
 
index a46e9bb847bd0ac52743f14ab07133cc9a98b231..3ed9c5e4d34e7bfbc51351a8475878424c325ab6 100644 (file)
@@ -21,7 +21,7 @@
  *  TODO:
  *     Enable cached programming for 2k page size chips
  *     Check, if mtd->ecctype should be set to MTD_ECC_HW
- *     if we have HW ecc support.
+ *     if we have HW ECC support.
  *     The AG-AND chips have nice features for speed improvement,
  *     which are not supported yet. Read / program 4 pages in one go.
  *     BBT table is not serialized, has to be fixed
@@ -113,21 +113,19 @@ static int check_offs_len(struct mtd_info *mtd,
 
        /* Start address must align on block boundary */
        if (ofs & ((1 << chip->phys_erase_shift) - 1)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Unaligned address\n", __func__);
+               pr_debug("%s: unaligned address\n", __func__);
                ret = -EINVAL;
        }
 
        /* Length must align on block boundary */
        if (len & ((1 << chip->phys_erase_shift) - 1)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Length not block aligned\n",
-                                       __func__);
+               pr_debug("%s: length not block aligned\n", __func__);
                ret = -EINVAL;
        }
 
        /* Do not allow past end of device */
        if (ofs + len > mtd->size) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Past end of device\n",
-                                       __func__);
+               pr_debug("%s: past end of device\n", __func__);
                ret = -EINVAL;
        }
 
@@ -136,9 +134,9 @@ static int check_offs_len(struct mtd_info *mtd,
 
 /**
  * nand_release_device - [GENERIC] release chip
- * @mtd:       MTD device structure
+ * @mtd: MTD device structure
  *
- * Deselect, release chip lock and wake up anyone waiting on the device
+ * Deselect, release chip lock and wake up anyone waiting on the device.
  */
 static void nand_release_device(struct mtd_info *mtd)
 {
@@ -157,9 +155,9 @@ static void nand_release_device(struct mtd_info *mtd)
 
 /**
  * nand_read_byte - [DEFAULT] read one byte from the chip
- * @mtd:       MTD device structure
+ * @mtd: MTD device structure
  *
- * Default read function for 8bit buswith
+ * Default read function for 8bit buswidth
  */
 static uint8_t nand_read_byte(struct mtd_info *mtd)
 {
@@ -169,10 +167,11 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
 
 /**
  * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
- * @mtd:       MTD device structure
+ * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
+ * @mtd: MTD device structure
+ *
+ * Default read function for 16bit buswidth with endianness conversion.
  *
- * Default read function for 16bit buswith with
- * endianess conversion
  */
 static uint8_t nand_read_byte16(struct mtd_info *mtd)
 {
@@ -182,10 +181,9 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
 
 /**
  * nand_read_word - [DEFAULT] read one word from the chip
- * @mtd:       MTD device structure
+ * @mtd: MTD device structure
  *
- * Default read function for 16bit buswith without
- * endianess conversion
+ * Default read function for 16bit buswidth without endianness conversion.
  */
 static u16 nand_read_word(struct mtd_info *mtd)
 {
@@ -195,8 +193,8 @@ static u16 nand_read_word(struct mtd_info *mtd)
 
 /**
  * nand_select_chip - [DEFAULT] control CE line
- * @mtd:       MTD device structure
- * @chipnr:    chipnumber to select, -1 for deselect
+ * @mtd: MTD device structure
+ * @chipnr: chipnumber to select, -1 for deselect
  *
  * Default select function for 1 chip devices.
  */
@@ -218,11 +216,11 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
 
 /**
  * nand_write_buf - [DEFAULT] write buffer to chip
- * @mtd:       MTD device structure
- * @buf:       data buffer
- * @len:       number of bytes to write
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
  *
- * Default write function for 8bit buswith
+ * Default write function for 8bit buswidth.
  */
 static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -235,11 +233,11 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 /**
  * nand_read_buf - [DEFAULT] read chip data into buffer
- * @mtd:       MTD device structure
- * @buf:       buffer to store date
- * @len:       number of bytes to read
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
  *
- * Default read function for 8bit buswith
+ * Default read function for 8bit buswidth.
  */
 static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
@@ -252,11 +250,11 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
 /**
  * nand_verify_buf - [DEFAULT] Verify chip data against buffer
- * @mtd:       MTD device structure
- * @buf:       buffer containing the data to compare
- * @len:       number of bytes to compare
+ * @mtd: MTD device structure
+ * @buf: buffer containing the data to compare
+ * @len: number of bytes to compare
  *
- * Default verify function for 8bit buswith
+ * Default verify function for 8bit buswidth.
  */
 static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -271,11 +269,11 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 /**
  * nand_write_buf16 - [DEFAULT] write buffer to chip
- * @mtd:       MTD device structure
- * @buf:       data buffer
- * @len:       number of bytes to write
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
  *
- * Default write function for 16bit buswith
+ * Default write function for 16bit buswidth.
  */
 static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -291,11 +289,11 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 /**
  * nand_read_buf16 - [DEFAULT] read chip data into buffer
- * @mtd:       MTD device structure
- * @buf:       buffer to store date
- * @len:       number of bytes to read
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
  *
- * Default read function for 16bit buswith
+ * Default read function for 16bit buswidth.
  */
 static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
@@ -310,11 +308,11 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 
 /**
  * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
- * @mtd:       MTD device structure
- * @buf:       buffer containing the data to compare
- * @len:       number of bytes to compare
+ * @mtd: MTD device structure
+ * @buf: buffer containing the data to compare
+ * @len: number of bytes to compare
  *
- * Default verify function for 16bit buswith
+ * Default verify function for 16bit buswidth.
  */
 static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -332,9 +330,9 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 /**
  * nand_block_bad - [DEFAULT] Read bad block marker from the chip
- * @mtd:       MTD device structure
- * @ofs:       offset from device start
- * @getchip:   0, if the chip is already selected
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ * @getchip: 0, if the chip is already selected
  *
  * Check, if the block is bad.
  */
@@ -344,7 +342,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
        struct nand_chip *chip = mtd->priv;
        u16 bad;
 
-       if (chip->options & NAND_BBT_SCANLASTPAGE)
+       if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
                ofs += mtd->erasesize - mtd->writesize;
 
        page = (int)(ofs >> chip->page_shift) & chip->pagemask;
@@ -384,11 +382,11 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 
 /**
  * nand_default_block_markbad - [DEFAULT] mark a block bad
- * @mtd:       MTD device structure
- * @ofs:       offset from device start
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
  *
- * This is the default implementation, which can be overridden by
- * a hardware specific driver.
+ * This is the default implementation, which can be overridden by a hardware
+ * specific driver.
 */
 static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
@@ -396,7 +394,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
        uint8_t buf[2] = { 0, 0 };
        int block, ret, i = 0;
 
-       if (chip->options & NAND_BBT_SCANLASTPAGE)
+       if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
                ofs += mtd->erasesize - mtd->writesize;
 
        /* Get block number */
@@ -404,33 +402,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
        if (chip->bbt)
                chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
-       /* Do we have a flash based bad block table ? */
-       if (chip->options & NAND_USE_FLASH_BBT)
+       /* Do we have a flash based bad block table? */
+       if (chip->bbt_options & NAND_BBT_USE_FLASH)
                ret = nand_update_bbt(mtd, ofs);
        else {
+               struct mtd_oob_ops ops;
+
                nand_get_device(chip, mtd, FL_WRITING);
 
-               /* Write to first two pages and to byte 1 and 6 if necessary.
-                * If we write to more than one location, the first error
-                * encountered quits the procedure. We write two bytes per
-                * location, so we dont have to mess with 16 bit access.
+               /*
+                * Write to first two pages if necessary. If we write to more
+                * than one location, the first error encountered quits the
+                * procedure. We write two bytes per location, so we dont have
+                * to mess with 16 bit access.
                 */
+               ops.len = ops.ooblen = 2;
+               ops.datbuf = NULL;
+               ops.oobbuf = buf;
+               ops.ooboffs = chip->badblockpos & ~0x01;
+               ops.mode = MTD_OPS_PLACE_OOB;
                do {
-                       chip->ops.len = chip->ops.ooblen = 2;
-                       chip->ops.datbuf = NULL;
-                       chip->ops.oobbuf = buf;
-                       chip->ops.ooboffs = chip->badblockpos & ~0x01;
-
-                       ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+                       ret = nand_do_write_oob(mtd, ofs, &ops);
 
-                       if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) {
-                               chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS
-                                       & ~0x01;
-                               ret = nand_do_write_oob(mtd, ofs, &chip->ops);
-                       }
                        i++;
                        ofs += mtd->writesize;
-               } while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) &&
+               } while (!ret && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE) &&
                                i < 2);
 
                nand_release_device(mtd);
@@ -443,16 +439,16 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
 /**
  * nand_check_wp - [GENERIC] check if the chip is write protected
- * @mtd:       MTD device structure
- * Check, if the device is write protected
+ * @mtd: MTD device structure
  *
- * The function expects, that the device is already selected
+ * Check, if the device is write protected. The function expects, that the
+ * device is already selected.
  */
 static int nand_check_wp(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
 
-       /* broken xD cards report WP despite being writable */
+       /* Broken xD cards report WP despite being writable */
        if (chip->options & NAND_BROKEN_XD)
                return 0;
 
@@ -463,10 +459,10 @@ static int nand_check_wp(struct mtd_info *mtd)
 
 /**
  * nand_block_checkbad - [GENERIC] Check if a block is marked bad
- * @mtd:       MTD device structure
- * @ofs:       offset from device start
- * @getchip:   0, if the chip is already selected
- * @allowbbt:  1, if its allowed to access the bbt area
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ * @getchip: 0, if the chip is already selected
+ * @allowbbt: 1, if its allowed to access the bbt area
  *
  * Check, if the block is bad. Either by reading the bad block table or
  * calling of the scan function.
@@ -485,8 +481,8 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
 
 /**
  * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
- * @mtd:       MTD device structure
- * @timeo:     Timeout
+ * @mtd: MTD device structure
+ * @timeo: Timeout
  *
  * Helper function for nand_wait_ready used when needing to wait in interrupt
  * context.
@@ -505,10 +501,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
        }
 }
 
-/*
- * Wait for the ready pin, after a command
- * The timeout is catched later.
- */
+/* Wait for the ready pin, after a command. The timeout is caught later. */
 void nand_wait_ready(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
@@ -519,7 +512,7 @@ void nand_wait_ready(struct mtd_info *mtd)
                return panic_nand_wait_ready(mtd, 400);
 
        led_trigger_event(nand_led_trigger, LED_FULL);
-       /* wait until command is processed or timeout occures */
+       /* Wait until command is processed or timeout occurs */
        do {
                if (chip->dev_ready(mtd))
                        break;
@@ -531,13 +524,13 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
 
 /**
  * nand_command - [DEFAULT] Send command to NAND device
- * @mtd:       MTD device structure
- * @command:   the command to be sent
- * @column:    the column address for this command, -1 if none
- * @page_addr: the page address for this command, -1 if none
+ * @mtd: MTD device structure
+ * @command: the command to be sent
+ * @column: the column address for this command, -1 if none
+ * @page_addr: the page address for this command, -1 if none
  *
- * Send command to NAND device. This function is used for small page
- * devices (256/512 Bytes per page)
+ * Send command to NAND device. This function is used for small page devices
+ * (256/512 Bytes per page).
  */
 static void nand_command(struct mtd_info *mtd, unsigned int command,
                         int column, int page_addr)
@@ -545,9 +538,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
        register struct nand_chip *chip = mtd->priv;
        int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
 
-       /*
-        * Write out the command to the device.
-        */
+       /* Write out the command to the device */
        if (command == NAND_CMD_SEQIN) {
                int readcmd;
 
@@ -567,9 +558,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
        }
        chip->cmd_ctrl(mtd, command, ctrl);
 
-       /*
-        * Address cycle, when necessary
-        */
+       /* Address cycle, when necessary */
        ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
        /* Serially input address */
        if (column != -1) {
@@ -590,8 +579,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
        chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
        /*
-        * program and erase have their own busy handlers
-        * status and sequential in needs no delay
+        * Program and erase have their own busy handlers status and sequential
+        * in needs no delay
         */
        switch (command) {
 
@@ -625,8 +614,10 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
                        return;
                }
        }
-       /* Apply this short delay always to ensure that we do wait tWB in
-        * any case on any machine. */
+       /*
+        * Apply this short delay always to ensure that we do wait tWB in
+        * any case on any machine.
+        */
        ndelay(100);
 
        nand_wait_ready(mtd);
@@ -634,14 +625,14 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
 
 /**
  * nand_command_lp - [DEFAULT] Send command to NAND large page device
- * @mtd:       MTD device structure
- * @command:   the command to be sent
- * @column:    the column address for this command, -1 if none
- * @page_addr: the page address for this command, -1 if none
+ * @mtd: MTD device structure
+ * @command: the command to be sent
+ * @column: the column address for this command, -1 if none
+ * @page_addr: the page address for this command, -1 if none
  *
  * Send command to NAND device. This is the version for the new large page
- * devices We dont have the separate regions as we have in the small page
- * devices.  We must emulate NAND_CMD_READOOB to keep the code compatible.
+ * devices. We don't have the separate regions as we have in the small page
+ * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
  */
 static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
                            int column, int page_addr)
@@ -683,8 +674,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
        chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
        /*
-        * program and erase have their own busy handlers
-        * status, sequential in, and deplete1 need no delay
+        * Program and erase have their own busy handlers status, sequential
+        * in, and deplete1 need no delay.
         */
        switch (command) {
 
@@ -698,14 +689,12 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
        case NAND_CMD_DEPLETE1:
                return;
 
-               /*
-                * read error status commands require only a short delay
-                */
        case NAND_CMD_STATUS_ERROR:
        case NAND_CMD_STATUS_ERROR0:
        case NAND_CMD_STATUS_ERROR1:
        case NAND_CMD_STATUS_ERROR2:
        case NAND_CMD_STATUS_ERROR3:
+               /* Read error status commands require only a short delay */
                udelay(chip->chip_delay);
                return;
 
@@ -739,7 +728,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
        default:
                /*
                 * If we don't have access to the busy pin, we apply the given
-                * command delay
+                * command delay.
                 */
                if (!chip->dev_ready) {
                        udelay(chip->chip_delay);
@@ -747,8 +736,10 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
                }
        }
 
-       /* Apply this short delay always to ensure that we do wait tWB in
-        * any case on any machine. */
+       /*
+        * Apply this short delay always to ensure that we do wait tWB in
+        * any case on any machine.
+        */
        ndelay(100);
 
        nand_wait_ready(mtd);
@@ -756,25 +747,25 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 
 /**
  * panic_nand_get_device - [GENERIC] Get chip for selected access
- * @chip:      the nand chip descriptor
- * @mtd:       MTD device structure
- * @new_state: the state which is requested
+ * @chip: the nand chip descriptor
+ * @mtd: MTD device structure
+ * @new_state: the state which is requested
  *
  * Used when in panic, no locks are taken.
  */
 static void panic_nand_get_device(struct nand_chip *chip,
                      struct mtd_info *mtd, int new_state)
 {
-       /* Hardware controller shared among independend devices */
+       /* Hardware controller shared among independent devices */
        chip->controller->active = chip;
        chip->state = new_state;
 }
 
 /**
  * nand_get_device - [GENERIC] Get chip for selected access
- * @chip:      the nand chip descriptor
- * @mtd:       MTD device structure
- * @new_state: the state which is requested
+ * @chip: the nand chip descriptor
+ * @mtd: MTD device structure
+ * @new_state: the state which is requested
  *
  * Get the device and lock it for exclusive access
  */
@@ -812,10 +803,10 @@ retry:
 }
 
 /**
- * panic_nand_wait - [GENERIC]  wait until the command is done
- * @mtd:       MTD device structure
- * @chip:      NAND chip structure
- * @timeo:     Timeout
+ * panic_nand_wait - [GENERIC] wait until the command is done
+ * @mtd: MTD device structure
+ * @chip: NAND chip structure
+ * @timeo: timeout
  *
  * Wait for command done. This is a helper function for nand_wait used when
  * we are in interrupt context. May happen when in panic and trying to write
@@ -838,13 +829,13 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_wait - [DEFAULT]  wait until the command is done
- * @mtd:       MTD device structure
- * @chip:      NAND chip structure
+ * nand_wait - [DEFAULT] wait until the command is done
+ * @mtd: MTD device structure
+ * @chip: NAND chip structure
  *
- * Wait for command done. This applies to erase and program only
- * Erase can take up to 400ms and program up to 20ms according to
- * general NAND and SmartMedia specs
+ * Wait for command done. This applies to erase and program only. Erase can
+ * take up to 400ms and program up to 20ms according to general NAND and
+ * SmartMedia specs.
  */
 static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
@@ -859,8 +850,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 
        led_trigger_event(nand_led_trigger, LED_FULL);
 
-       /* Apply this short delay always to ensure that we do wait tWB in
-        * any case on any machine. */
+       /*
+        * Apply this short delay always to ensure that we do wait tWB in any
+        * case on any machine.
+        */
        ndelay(100);
 
        if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
@@ -890,16 +883,15 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 
 /**
  * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
- *
  * @mtd: mtd info
  * @ofs: offset to start unlock from
  * @len: length to unlock
- * @invert:   when = 0, unlock the range of blocks within the lower and
- *                      upper boundary address
- *            when = 1, unlock the range of blocks outside the boundaries
- *                      of the lower and upper boundary address
+ * @invert: when = 0, unlock the range of blocks within the lower and
+ *                    upper boundary address
+ *          when = 1, unlock the range of blocks outside the boundaries
+ *                    of the lower and upper boundary address
  *
- * return - unlock status
+ * Returs unlock status.
  */
 static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
                                        uint64_t len, int invert)
@@ -919,10 +911,9 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
 
        /* Call wait ready function */
        status = chip->waitfunc(mtd, chip);
-       udelay(1000);
        /* See if device thinks it succeeded */
        if (status & 0x01) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
+               pr_debug("%s: error status = 0x%08x\n",
                                        __func__, status);
                ret = -EIO;
        }
@@ -932,12 +923,11 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
 
 /**
  * nand_unlock - [REPLACEABLE] unlocks specified locked blocks
- *
  * @mtd: mtd info
  * @ofs: offset to start unlock from
  * @len: length to unlock
  *
- * return - unlock status
+ * Returns unlock status.
  */
 int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
@@ -945,7 +935,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
        int chipnr;
        struct nand_chip *chip = mtd->priv;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+       pr_debug("%s: start = 0x%012llx, len = %llu\n",
                        __func__, (unsigned long long)ofs, len);
 
        if (check_offs_len(mtd, ofs, len))
@@ -964,7 +954,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+               pr_debug("%s: device is write protected!\n",
                                        __func__);
                ret = -EIO;
                goto out;
@@ -981,18 +971,16 @@ EXPORT_SYMBOL(nand_unlock);
 
 /**
  * nand_lock - [REPLACEABLE] locks all blocks present in the device
- *
  * @mtd: mtd info
  * @ofs: offset to start unlock from
  * @len: length to unlock
  *
- * return - lock status
+ * This feature is not supported in many NAND parts. 'Micron' NAND parts do
+ * have this feature, but it allows only to lock all blocks, not for specified
+ * range for block. Implementing 'lock' feature by making use of 'unlock', for
+ * now.
  *
- * This feature is not supported in many NAND parts. 'Micron' NAND parts
- * do have this feature, but it allows only to lock all blocks, not for
- * specified range for block.
- *
- * Implementing 'lock' feature by making use of 'unlock', for now.
+ * Returns lock status.
  */
 int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
@@ -1000,7 +988,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
        int chipnr, status, page;
        struct nand_chip *chip = mtd->priv;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+       pr_debug("%s: start = 0x%012llx, len = %llu\n",
                        __func__, (unsigned long long)ofs, len);
 
        if (check_offs_len(mtd, ofs, len))
@@ -1015,7 +1003,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+               pr_debug("%s: device is write protected!\n",
                                        __func__);
                status = MTD_ERASE_FAILED;
                ret = -EIO;
@@ -1028,10 +1016,9 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
        /* Call wait ready function */
        status = chip->waitfunc(mtd, chip);
-       udelay(1000);
        /* See if device thinks it succeeded */
        if (status & 0x01) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
+               pr_debug("%s: error status = 0x%08x\n",
                                        __func__, status);
                ret = -EIO;
                goto out;
@@ -1047,13 +1034,13 @@ out:
 EXPORT_SYMBOL(nand_lock);
 
 /**
- * nand_read_page_raw - [Intern] read raw page data without ecc
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       buffer to store read data
- * @page:      page number to read
+ * nand_read_page_raw - [INTERN] read raw page data without ecc
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
- * Not for syndrome calculating ecc controllers, which use a special oob layout
+ * Not for syndrome calculating ECC controllers, which use a special oob layout.
  */
 static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
                              uint8_t *buf, int page)
@@ -1064,11 +1051,11 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       buffer to store read data
- * @page:      page number to read
+ * nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
  * We need a special oob layout and handling even when OOB isn't used.
  */
@@ -1107,11 +1094,11 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
 }
 
 /**
- * nand_read_page_swecc - [REPLACABLE] software ecc based page read function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       buffer to store read data
- * @page:      page number to read
+ * nand_read_page_swecc - [REPLACEABLE] software ECC based page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  */
 static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
                                uint8_t *buf, int page)
@@ -1148,12 +1135,12 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @data_offs: offset of requested data within the page
- * @readlen:   data length
- * @bufpoi:    buffer to store read data
+ * nand_read_subpage - [REPLACEABLE] software ECC based sub-page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @data_offs: offset of requested data within the page
+ * @readlen: data length
+ * @bufpoi: buffer to store read data
  */
 static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
                        uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
@@ -1166,12 +1153,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
        int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
        int index = 0;
 
-       /* Column address wihin the page aligned to ECC size (256bytes). */
+       /* Column address within the page aligned to ECC size (256bytes) */
        start_step = data_offs / chip->ecc.size;
        end_step = (data_offs + readlen - 1) / chip->ecc.size;
        num_steps = end_step - start_step + 1;
 
-       /* Data size aligned to ECC ecc.size*/
+       /* Data size aligned to ECC ecc.size */
        datafrag_len = num_steps * chip->ecc.size;
        eccfrag_len = num_steps * chip->ecc.bytes;
 
@@ -1183,13 +1170,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
        p = bufpoi + data_col_addr;
        chip->read_buf(mtd, p, datafrag_len);
 
-       /* Calculate  ECC */
+       /* Calculate ECC */
        for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
                chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
 
-       /* The performance is faster if to position offsets
-          according to ecc.pos. Let make sure here that
-          there are no gaps in ecc positions */
+       /*
+        * The performance is faster if we position offsets according to
+        * ecc.pos. Let's make sure that there are no gaps in ECC positions.
+        */
        for (i = 0; i < eccfrag_len - 1; i++) {
                if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
                        eccpos[i + start_step * chip->ecc.bytes + 1]) {
@@ -1201,8 +1189,10 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
                chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
                chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
        } else {
-               /* send the command to read the particular ecc bytes */
-               /* take care about buswidth alignment in read_buf */
+               /*
+                * Send the command to read the particular ECC bytes take care
+                * about buswidth alignment in read_buf.
+                */
                index = start_step * chip->ecc.bytes;
 
                aligned_pos = eccpos[index] & ~(busw - 1);
@@ -1235,13 +1225,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       buffer to store read data
- * @page:      page number to read
+ * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
- * Not for syndrome calculating ecc controllers which need a special oob layout
+ * Not for syndrome calculating ECC controllers which need a special oob layout.
  */
 static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
                                uint8_t *buf, int page)
@@ -1280,18 +1270,17 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       buffer to store read data
- * @page:      page number to read
+ * nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
- * Hardware ECC for large page chips, require OOB to be read first.
- * For this ECC mode, the write_page method is re-used from ECC_HW.
- * These methods read/write ECC from the OOB area, unlike the
- * ECC_HW_SYNDROME support with multiple ECC steps, follows the
- * "infix ECC" scheme and reads/writes ECC from the data area, by
- * overwriting the NAND manufacturer bad block markings.
+ * Hardware ECC for large page chips, require OOB to be read first. For this
+ * ECC mode, the write_page method is re-used from ECC_HW. These methods
+ * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
+ * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
+ * the data area, by overwriting the NAND manufacturer bad block markings.
  */
 static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
        struct nand_chip *chip, uint8_t *buf, int page)
@@ -1329,14 +1318,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
 }
 
 /**
- * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       buffer to store read data
- * @page:      page number to read
+ * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
- * The hw generator calculates the error syndrome automatically. Therefor
- * we need a special oob layout and handling.
+ * The hw generator calculates the error syndrome automatically. Therefore we
+ * need a special oob layout and handling.
  */
 static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
                                   uint8_t *buf, int page)
@@ -1384,29 +1373,29 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_transfer_oob - [Internal] Transfer oob to client buffer
- * @chip:      nand chip structure
- * @oob:       oob destination address
- * @ops:       oob ops structure
- * @len:       size of oob to transfer
+ * nand_transfer_oob - [INTERN] Transfer oob to client buffer
+ * @chip: nand chip structure
+ * @oob: oob destination address
+ * @ops: oob ops structure
+ * @len: size of oob to transfer
  */
 static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
                                  struct mtd_oob_ops *ops, size_t len)
 {
        switch (ops->mode) {
 
-       case MTD_OOB_PLACE:
-       case MTD_OOB_RAW:
+       case MTD_OPS_PLACE_OOB:
+       case MTD_OPS_RAW:
                memcpy(oob, chip->oob_poi + ops->ooboffs, len);
                return oob + len;
 
-       case MTD_OOB_AUTO: {
+       case MTD_OPS_AUTO_OOB: {
                struct nand_oobfree *free = chip->ecc.layout->oobfree;
                uint32_t boffs = 0, roffs = ops->ooboffs;
                size_t bytes = 0;
 
                for (; free->length && len; free++, len -= bytes) {
-                       /* Read request not from offset 0 ? */
+                       /* Read request not from offset 0? */
                        if (unlikely(roffs)) {
                                if (roffs >= free->length) {
                                        roffs -= free->length;
@@ -1432,11 +1421,10 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
 }
 
 /**
- * nand_do_read_ops - [Internal] Read data with ECC
- *
- * @mtd:       MTD device structure
- * @from:      offset to read from
- * @ops:       oob ops structure
+ * nand_do_read_ops - [INTERN] Read data with ECC
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob ops structure
  *
  * Internal function. Called with chip held.
  */
@@ -1451,7 +1439,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
        int ret = 0;
        uint32_t readlen = ops->len;
        uint32_t oobreadlen = ops->ooblen;
-       uint32_t max_oobsize = ops->mode == MTD_OOB_AUTO ?
+       uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ?
                mtd->oobavail : mtd->oobsize;
 
        uint8_t *bufpoi, *oob, *buf;
@@ -1473,7 +1461,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                bytes = min(mtd->writesize - col, readlen);
                aligned = (bytes == mtd->writesize);
 
-               /* Is the current page in the buffer ? */
+               /* Is the current page in the buffer? */
                if (realpage != chip->pagebuf || oob) {
                        bufpoi = aligned ? buf : chip->buffers->databuf;
 
@@ -1483,7 +1471,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                        }
 
                        /* Now read the page into the buffer */
-                       if (unlikely(ops->mode == MTD_OOB_RAW))
+                       if (unlikely(ops->mode == MTD_OPS_RAW))
                                ret = chip->ecc.read_page_raw(mtd, chip,
                                                              bufpoi, page);
                        else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
@@ -1492,14 +1480,22 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                        else
                                ret = chip->ecc.read_page(mtd, chip, bufpoi,
                                                          page);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               if (!aligned)
+                                       /* Invalidate page cache */
+                                       chip->pagebuf = -1;
                                break;
+                       }
 
                        /* Transfer not aligned data */
                        if (!aligned) {
                                if (!NAND_SUBPAGE_READ(chip) && !oob &&
-                                   !(mtd->ecc_stats.failed - stats.failed))
+                                   !(mtd->ecc_stats.failed - stats.failed) &&
+                                   (ops->mode != MTD_OPS_RAW))
                                        chip->pagebuf = realpage;
+                               else
+                                       /* Invalidate page cache */
+                                       chip->pagebuf = -1;
                                memcpy(buf, chip->buffers->databuf + col, bytes);
                        }
 
@@ -1539,7 +1535,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                if (!readlen)
                        break;
 
-               /* For subsequent reads align to page boundary. */
+               /* For subsequent reads align to page boundary */
                col = 0;
                /* Increment page address */
                realpage++;
@@ -1552,8 +1548,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                        chip->select_chip(mtd, chipnr);
                }
 
-               /* Check, if the chip supports auto page increment
-                * or if we have hit a block boundary.
+               /*
+                * Check, if the chip supports auto page increment or if we
+                * have hit a block boundary.
                 */
                if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
                        sndcmd = 1;
@@ -1574,18 +1571,19 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 
 /**
  * nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc
- * @mtd:       MTD device structure
- * @from:      offset to read from
- * @len:       number of bytes to read
- * @retlen:    pointer to variable to store the number of read bytes
- * @buf:       the databuffer to put data
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @len: number of bytes to read
+ * @retlen: pointer to variable to store the number of read bytes
+ * @buf: the databuffer to put data
  *
- * Get hold of the chip and call nand_do_read
+ * Get hold of the chip and call nand_do_read.
  */
 static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
                     size_t *retlen, uint8_t *buf)
 {
        struct nand_chip *chip = mtd->priv;
+       struct mtd_oob_ops ops;
        int ret;
 
        /* Do not allow reads past end of device */
@@ -1596,13 +1594,14 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        nand_get_device(chip, mtd, FL_READING);
 
-       chip->ops.len = len;
-       chip->ops.datbuf = buf;
-       chip->ops.oobbuf = NULL;
+       ops.len = len;
+       ops.datbuf = buf;
+       ops.oobbuf = NULL;
+       ops.mode = 0;
 
-       ret = nand_do_read_ops(mtd, from, &chip->ops);
+       ret = nand_do_read_ops(mtd, from, &ops);
 
-       *retlen = chip->ops.retlen;
+       *retlen = ops.retlen;
 
        nand_release_device(mtd);
 
@@ -1610,11 +1609,11 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
 }
 
 /**
- * nand_read_oob_std - [REPLACABLE] the most common OOB data read function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @page:      page number to read
- * @sndcmd:    flag whether to issue read command or not
+ * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to read
+ * @sndcmd: flag whether to issue read command or not
  */
 static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
                             int page, int sndcmd)
@@ -1628,12 +1627,12 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
+ * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC
  *                         with syndromes
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @page:      page number to read
- * @sndcmd:    flag whether to issue read command or not
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to read
+ * @sndcmd: flag whether to issue read command or not
  */
 static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
                                  int page, int sndcmd)
@@ -1667,10 +1666,10 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_oob_std - [REPLACABLE] the most common OOB data write function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @page:      page number to write
+ * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to write
  */
 static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
                              int page)
@@ -1690,11 +1689,11 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
- *                          with syndrome - only for large page flash !
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @page:      page number to write
+ * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC
+ *                          with syndrome - only for large page flash
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to write
  */
 static int nand_write_oob_syndrome(struct mtd_info *mtd,
                                   struct nand_chip *chip, int page)
@@ -1749,34 +1748,37 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
 }
 
 /**
- * nand_do_read_oob - [Intern] NAND read out-of-band
- * @mtd:       MTD device structure
- * @from:      offset to read from
- * @ops:       oob operations description structure
+ * nand_do_read_oob - [INTERN] NAND read out-of-band
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operations description structure
  *
- * NAND read out-of-band data from the spare area
+ * NAND read out-of-band data from the spare area.
  */
 static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
                            struct mtd_oob_ops *ops)
 {
        int page, realpage, chipnr, sndcmd = 1;
        struct nand_chip *chip = mtd->priv;
+       struct mtd_ecc_stats stats;
        int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
        int readlen = ops->ooblen;
        int len;
        uint8_t *buf = ops->oobbuf;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",
+       pr_debug("%s: from = 0x%08Lx, len = %i\n",
                        __func__, (unsigned long long)from, readlen);
 
-       if (ops->mode == MTD_OOB_AUTO)
+       stats = mtd->ecc_stats;
+
+       if (ops->mode == MTD_OPS_AUTO_OOB)
                len = chip->ecc.layout->oobavail;
        else
                len = mtd->oobsize;
 
        if (unlikely(ops->ooboffs >= len)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start read "
-                                       "outside oob\n", __func__);
+               pr_debug("%s: attempt to start read outside oob\n",
+                               __func__);
                return -EINVAL;
        }
 
@@ -1784,8 +1786,8 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
        if (unlikely(from >= mtd->size ||
                     ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
                                        (from >> chip->page_shift)) * len)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read beyond end "
-                                       "of device\n", __func__);
+               pr_debug("%s: attempt to read beyond end of device\n",
+                               __func__);
                return -EINVAL;
        }
 
@@ -1797,7 +1799,10 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
        page = realpage & chip->pagemask;
 
        while (1) {
-               sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
+               if (ops->mode == MTD_OPS_RAW)
+                       sndcmd = chip->ecc.read_oob_raw(mtd, chip, page, sndcmd);
+               else
+                       sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
 
                len = min(len, readlen);
                buf = nand_transfer_oob(chip, buf, ops, len);
@@ -1830,24 +1835,29 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
                        chip->select_chip(mtd, chipnr);
                }
 
-               /* Check, if the chip supports auto page increment
-                * or if we have hit a block boundary.
+               /*
+                * Check, if the chip supports auto page increment or if we
+                * have hit a block boundary.
                 */
                if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
                        sndcmd = 1;
        }
 
        ops->oobretlen = ops->ooblen;
-       return 0;
+
+       if (mtd->ecc_stats.failed - stats.failed)
+               return -EBADMSG;
+
+       return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
 
 /**
  * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
- * @mtd:       MTD device structure
- * @from:      offset to read from
- * @ops:       oob operation description structure
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operation description structure
  *
- * NAND read data and/or out-of-band data
+ * NAND read data and/or out-of-band data.
  */
 static int nand_read_oob(struct mtd_info *mtd, loff_t from,
                         struct mtd_oob_ops *ops)
@@ -1859,17 +1869,17 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 
        /* Do not allow reads past end of device */
        if (ops->datbuf && (from + ops->len) > mtd->size) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read "
-                               "beyond end of device\n", __func__);
+               pr_debug("%s: attempt to read beyond end of device\n",
+                               __func__);
                return -EINVAL;
        }
 
        nand_get_device(chip, mtd, FL_READING);
 
        switch (ops->mode) {
-       case MTD_OOB_PLACE:
-       case MTD_OOB_AUTO:
-       case MTD_OOB_RAW:
+       case MTD_OPS_PLACE_OOB:
+       case MTD_OPS_AUTO_OOB:
+       case MTD_OPS_RAW:
                break;
 
        default:
@@ -1888,12 +1898,12 @@ out:
 
 
 /**
- * nand_write_page_raw - [Intern] raw page write function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       data buffer
+ * nand_write_page_raw - [INTERN] raw page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  *
- * Not for syndrome calculating ecc controllers, which use a special oob layout
+ * Not for syndrome calculating ECC controllers, which use a special oob layout.
  */
 static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
                                const uint8_t *buf)
@@ -1903,10 +1913,10 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_page_raw_syndrome - [Intern] raw page write function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       data buffer
+ * nand_write_page_raw_syndrome - [INTERN] raw page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  *
  * We need a special oob layout and handling even when ECC isn't checked.
  */
@@ -1942,10 +1952,10 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
                chip->write_buf(mtd, oob, size);
 }
 /**
- * nand_write_page_swecc - [REPLACABLE] software ecc based page write function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       data buffer
+ * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  */
 static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
                                  const uint8_t *buf)
@@ -1957,7 +1967,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
        const uint8_t *p = buf;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
 
-       /* Software ecc calculation */
+       /* Software ECC calculation */
        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
                chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
@@ -1968,10 +1978,10 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       data buffer
+ * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  */
 static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
                                  const uint8_t *buf)
@@ -1996,13 +2006,13 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
- * @mtd:       mtd info structure
- * @chip:      nand chip info structure
- * @buf:       data buffer
+ * nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  *
- * The hw generator calculates the error syndrome automatically. Therefor
- * we need a special oob layout and handling.
+ * The hw generator calculates the error syndrome automatically. Therefore we
+ * need a special oob layout and handling.
  */
 static void nand_write_page_syndrome(struct mtd_info *mtd,
                                    struct nand_chip *chip, const uint8_t *buf)
@@ -2041,12 +2051,12 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
 
 /**
  * nand_write_page - [REPLACEABLE] write one page
- * @mtd:       MTD device structure
- * @chip:      NAND chip descriptor
- * @buf:       the data to write
- * @page:      page number to write
- * @cached:    cached programming
- * @raw:       use _raw version of write_page
+ * @mtd: MTD device structure
+ * @chip: NAND chip descriptor
+ * @buf: the data to write
+ * @page: page number to write
+ * @cached: cached programming
+ * @raw: use _raw version of write_page
  */
 static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                           const uint8_t *buf, int page, int cached, int raw)
@@ -2061,8 +2071,8 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                chip->ecc.write_page(mtd, chip, buf);
 
        /*
-        * Cached progamming disabled for now, Not sure if its worth the
-        * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
+        * Cached progamming disabled for now. Not sure if it's worth the
+        * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s).
         */
        cached = 0;
 
@@ -2072,7 +2082,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                status = chip->waitfunc(mtd, chip);
                /*
                 * See if operation failed and additional status checks are
-                * available
+                * available.
                 */
                if ((status & NAND_STATUS_FAIL) && (chip->errstat))
                        status = chip->errstat(mtd, chip, FL_WRITING, status,
@@ -2096,29 +2106,37 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_fill_oob - [Internal] Transfer client buffer to oob
- * @chip:      nand chip structure
- * @oob:       oob data buffer
- * @len:       oob data write length
- * @ops:       oob ops structure
+ * nand_fill_oob - [INTERN] Transfer client buffer to oob
+ * @mtd: MTD device structure
+ * @oob: oob data buffer
+ * @len: oob data write length
+ * @ops: oob ops structure
  */
-static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
-                                               struct mtd_oob_ops *ops)
+static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
+                             struct mtd_oob_ops *ops)
 {
+       struct nand_chip *chip = mtd->priv;
+
+       /*
+        * Initialise to all 0xFF, to avoid the possibility of left over OOB
+        * data from a previous OOB read.
+        */
+       memset(chip->oob_poi, 0xff, mtd->oobsize);
+
        switch (ops->mode) {
 
-       case MTD_OOB_PLACE:
-       case MTD_OOB_RAW:
+       case MTD_OPS_PLACE_OOB:
+       case MTD_OPS_RAW:
                memcpy(chip->oob_poi + ops->ooboffs, oob, len);
                return oob + len;
 
-       case MTD_OOB_AUTO: {
+       case MTD_OPS_AUTO_OOB: {
                struct nand_oobfree *free = chip->ecc.layout->oobfree;
                uint32_t boffs = 0, woffs = ops->ooboffs;
                size_t bytes = 0;
 
                for (; free->length && len; free++, len -= bytes) {
-                       /* Write request not from offset 0 ? */
+                       /* Write request not from offset 0? */
                        if (unlikely(woffs)) {
                                if (woffs >= free->length) {
                                        woffs -= free->length;
@@ -2146,12 +2164,12 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
 #define NOTALIGNED(x)  ((x & (chip->subpagesize - 1)) != 0)
 
 /**
- * nand_do_write_ops - [Internal] NAND write with ECC
- * @mtd:       MTD device structure
- * @to:                offset to write to
- * @ops:       oob operations description structure
+ * nand_do_write_ops - [INTERN] NAND write with ECC
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operations description structure
  *
- * NAND write with ECC
+ * NAND write with ECC.
  */
 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
                             struct mtd_oob_ops *ops)
@@ -2161,7 +2179,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
        uint32_t writelen = ops->len;
 
        uint32_t oobwritelen = ops->ooblen;
-       uint32_t oobmaxlen = ops->mode == MTD_OOB_AUTO ?
+       uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
                                mtd->oobavail : mtd->oobsize;
 
        uint8_t *oob = ops->oobbuf;
@@ -2172,10 +2190,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
        if (!writelen)
                return 0;
 
-       /* reject writes, which are not page aligned */
+       /* Reject writes, which are not page aligned */
        if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
-               printk(KERN_NOTICE "%s: Attempt to write not "
-                               "page aligned data\n", __func__);
+               pr_notice("%s: attempt to write non page aligned data\n",
+                          __func__);
                return -EINVAL;
        }
 
@@ -2201,10 +2219,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
            (chip->pagebuf << chip->page_shift) < (to + ops->len))
                chip->pagebuf = -1;
 
-       /* If we're not given explicit OOB data, let it be 0xFF */
-       if (likely(!oob))
-               memset(chip->oob_poi, 0xff, mtd->oobsize);
-
        /* Don't allow multipage oob writes with offset */
        if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
                return -EINVAL;
@@ -2214,7 +2228,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
                int cached = writelen > bytes && page != blockmask;
                uint8_t *wbuf = buf;
 
-               /* Partial page write ? */
+               /* Partial page write? */
                if (unlikely(column || writelen < (mtd->writesize - 1))) {
                        cached = 0;
                        bytes = min_t(int, bytes - column, (int) writelen);
@@ -2226,12 +2240,15 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 
                if (unlikely(oob)) {
                        size_t len = min(oobwritelen, oobmaxlen);
-                       oob = nand_fill_oob(chip, oob, len, ops);
+                       oob = nand_fill_oob(mtd, oob, len, ops);
                        oobwritelen -= len;
+               } else {
+                       /* We still need to erase leftover OOB data */
+                       memset(chip->oob_poi, 0xff, mtd->oobsize);
                }
 
                ret = chip->write_page(mtd, chip, wbuf, page, cached,
-                                      (ops->mode == MTD_OOB_RAW));
+                                      (ops->mode == MTD_OPS_RAW));
                if (ret)
                        break;
 
@@ -2260,11 +2277,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 
 /**
  * panic_nand_write - [MTD Interface] NAND write with ECC
- * @mtd:       MTD device structure
- * @to:                offset to write to
- * @len:       number of bytes to write
- * @retlen:    pointer to variable to store the number of written bytes
- * @buf:       the data to write
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
  *
  * NAND write with ECC. Used when performing writes in interrupt context, this
  * may for example be called by mtdoops when writing an oops while in panic.
@@ -2273,6 +2290,7 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
                            size_t *retlen, const uint8_t *buf)
 {
        struct nand_chip *chip = mtd->priv;
+       struct mtd_oob_ops ops;
        int ret;
 
        /* Do not allow reads past end of device */
@@ -2281,36 +2299,38 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
        if (!len)
                return 0;
 
-       /* Wait for the device to get ready */
+       /* Wait for the device to get ready */
        panic_nand_wait(mtd, chip, 400);
 
-       /* Grab the device */
+       /* Grab the device */
        panic_nand_get_device(chip, mtd, FL_WRITING);
 
-       chip->ops.len = len;
-       chip->ops.datbuf = (uint8_t *)buf;
-       chip->ops.oobbuf = NULL;
+       ops.len = len;
+       ops.datbuf = (uint8_t *)buf;
+       ops.oobbuf = NULL;
+       ops.mode = 0;
 
-       ret = nand_do_write_ops(mtd, to, &chip->ops);
+       ret = nand_do_write_ops(mtd, to, &ops);
 
-       *retlen = chip->ops.retlen;
+       *retlen = ops.retlen;
        return ret;
 }
 
 /**
  * nand_write - [MTD Interface] NAND write with ECC
- * @mtd:       MTD device structure
- * @to:                offset to write to
- * @len:       number of bytes to write
- * @retlen:    pointer to variable to store the number of written bytes
- * @buf:       the data to write
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
  *
- * NAND write with ECC
+ * NAND write with ECC.
  */
 static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
                          size_t *retlen, const uint8_t *buf)
 {
        struct nand_chip *chip = mtd->priv;
+       struct mtd_oob_ops ops;
        int ret;
 
        /* Do not allow reads past end of device */
@@ -2321,13 +2341,14 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
 
        nand_get_device(chip, mtd, FL_WRITING);
 
-       chip->ops.len = len;
-       chip->ops.datbuf = (uint8_t *)buf;
-       chip->ops.oobbuf = NULL;
+       ops.len = len;
+       ops.datbuf = (uint8_t *)buf;
+       ops.oobbuf = NULL;
+       ops.mode = 0;
 
-       ret = nand_do_write_ops(mtd, to, &chip->ops);
+       ret = nand_do_write_ops(mtd, to, &ops);
 
-       *retlen = chip->ops.retlen;
+       *retlen = ops.retlen;
 
        nand_release_device(mtd);
 
@@ -2336,11 +2357,11 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
 
 /**
  * nand_do_write_oob - [MTD Interface] NAND write out-of-band
- * @mtd:       MTD device structure
- * @to:                offset to write to
- * @ops:       oob operation description structure
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operation description structure
  *
- * NAND write out-of-band
+ * NAND write out-of-band.
  */
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
                             struct mtd_oob_ops *ops)
@@ -2348,24 +2369,24 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
        int chipnr, page, status, len;
        struct nand_chip *chip = mtd->priv;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
+       pr_debug("%s: to = 0x%08x, len = %i\n",
                         __func__, (unsigned int)to, (int)ops->ooblen);
 
-       if (ops->mode == MTD_OOB_AUTO)
+       if (ops->mode == MTD_OPS_AUTO_OOB)
                len = chip->ecc.layout->oobavail;
        else
                len = mtd->oobsize;
 
        /* Do not allow write past end of page */
        if ((ops->ooboffs + ops->ooblen) > len) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to write "
-                               "past end of page\n", __func__);
+               pr_debug("%s: attempt to write past end of page\n",
+                               __func__);
                return -EINVAL;
        }
 
        if (unlikely(ops->ooboffs >= len)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start "
-                               "write outside oob\n", __func__);
+               pr_debug("%s: attempt to start write outside oob\n",
+                               __func__);
                return -EINVAL;
        }
 
@@ -2374,8 +2395,8 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
                     ops->ooboffs + ops->ooblen >
                        ((mtd->size >> chip->page_shift) -
                         (to >> chip->page_shift)) * len)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
-                               "end of device\n", __func__);
+               pr_debug("%s: attempt to write beyond end of device\n",
+                               __func__);
                return -EINVAL;
        }
 
@@ -2401,10 +2422,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
        if (page == chip->pagebuf)
                chip->pagebuf = -1;
 
-       memset(chip->oob_poi, 0xff, mtd->oobsize);
-       nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops);
-       status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
-       memset(chip->oob_poi, 0xff, mtd->oobsize);
+       nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops);
+
+       if (ops->mode == MTD_OPS_RAW)
+               status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask);
+       else
+               status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
 
        if (status)
                return status;
@@ -2416,9 +2439,9 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 
 /**
  * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
- * @mtd:       MTD device structure
- * @to:                offset to write to
- * @ops:       oob operation description structure
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operation description structure
  */
 static int nand_write_oob(struct mtd_info *mtd, loff_t to,
                          struct mtd_oob_ops *ops)
@@ -2430,17 +2453,17 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 
        /* Do not allow writes past end of device */
        if (ops->datbuf && (to + ops->len) > mtd->size) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
-                               "end of device\n", __func__);
+               pr_debug("%s: attempt to write beyond end of device\n",
+                               __func__);
                return -EINVAL;
        }
 
        nand_get_device(chip, mtd, FL_WRITING);
 
        switch (ops->mode) {
-       case MTD_OOB_PLACE:
-       case MTD_OOB_AUTO:
-       case MTD_OOB_RAW:
+       case MTD_OPS_PLACE_OOB:
+       case MTD_OPS_AUTO_OOB:
+       case MTD_OPS_RAW:
                break;
 
        default:
@@ -2458,11 +2481,11 @@ out:
 }
 
 /**
- * single_erease_cmd - [GENERIC] NAND standard block erase command function
- * @mtd:       MTD device structure
- * @page:      the page address of the block which will be erased
+ * single_erase_cmd - [GENERIC] NAND standard block erase command function
+ * @mtd: MTD device structure
+ * @page: the page address of the block which will be erased
  *
- * Standard erase command for NAND chips
+ * Standard erase command for NAND chips.
  */
 static void single_erase_cmd(struct mtd_info *mtd, int page)
 {
@@ -2473,12 +2496,11 @@ static void single_erase_cmd(struct mtd_info *mtd, int page)
 }
 
 /**
- * multi_erease_cmd - [GENERIC] AND specific block erase command function
- * @mtd:       MTD device structure
- * @page:      the page address of the block which will be erased
+ * multi_erase_cmd - [GENERIC] AND specific block erase command function
+ * @mtd: MTD device structure
+ * @page: the page address of the block which will be erased
  *
- * AND multi block erase command function
- * Erase 4 consecutive blocks
+ * AND multi block erase command function. Erase 4 consecutive blocks.
  */
 static void multi_erase_cmd(struct mtd_info *mtd, int page)
 {
@@ -2493,10 +2515,10 @@ static void multi_erase_cmd(struct mtd_info *mtd, int page)
 
 /**
  * nand_erase - [MTD Interface] erase block(s)
- * @mtd:       MTD device structure
- * @instr:     erase instruction
+ * @mtd: MTD device structure
+ * @instr: erase instruction
  *
- * Erase one ore more blocks
+ * Erase one ore more blocks.
  */
 static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
@@ -2505,12 +2527,12 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 #define BBT_PAGE_MASK  0xffffff3f
 /**
- * nand_erase_nand - [Internal] erase block(s)
- * @mtd:       MTD device structure
- * @instr:     erase instruction
- * @allowbbt:  allow erasing the bbt area
+ * nand_erase_nand - [INTERN] erase block(s)
+ * @mtd: MTD device structure
+ * @instr: erase instruction
+ * @allowbbt: allow erasing the bbt area
  *
- * Erase one ore more blocks
+ * Erase one ore more blocks.
  */
 int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
                    int allowbbt)
@@ -2521,9 +2543,9 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
        unsigned int bbt_masked_page = 0xffffffff;
        loff_t len;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
-                               __func__, (unsigned long long)instr->addr,
-                               (unsigned long long)instr->len);
+       pr_debug("%s: start = 0x%012llx, len = %llu\n",
+                       __func__, (unsigned long long)instr->addr,
+                       (unsigned long long)instr->len);
 
        if (check_offs_len(mtd, instr->addr, instr->len))
                return -EINVAL;
@@ -2545,8 +2567,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
-                                       __func__);
+               pr_debug("%s: device is write protected!\n",
+                               __func__);
                instr->state = MTD_ERASE_FAILED;
                goto erase_exit;
        }
@@ -2555,7 +2577,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
         * If BBT requires refresh, set the BBT page mask to see if the BBT
         * should be rewritten. Otherwise the mask is set to 0xffffffff which
         * can not be matched. This is also done when the bbt is actually
-        * erased to avoid recusrsive updates
+        * erased to avoid recursive updates.
         */
        if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
                bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
@@ -2566,20 +2588,18 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
        instr->state = MTD_ERASING;
 
        while (len) {
-               /*
-                * heck if we have a bad block, we do not erase bad blocks !
-                */
+               /* Heck if we have a bad block, we do not erase bad blocks! */
                if (nand_block_checkbad(mtd, ((loff_t) page) <<
                                        chip->page_shift, 0, allowbbt)) {
-                       printk(KERN_WARNING "%s: attempt to erase a bad block "
-                                       "at page 0x%08x\n", __func__, page);
+                       pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
+                                   __func__, page);
                        instr->state = MTD_ERASE_FAILED;
                        goto erase_exit;
                }
 
                /*
                 * Invalidate the page cache, if we erase the block which
-                * contains the current cached page
+                * contains the current cached page.
                 */
                if (page <= chip->pagebuf && chip->pagebuf <
                    (page + pages_per_block))
@@ -2599,8 +2619,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
                /* See if block erase succeeded */
                if (status & NAND_STATUS_FAIL) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed erase, "
-                                       "page 0x%08x\n", __func__, page);
+                       pr_debug("%s: failed erase, page 0x%08x\n",
+                                       __func__, page);
                        instr->state = MTD_ERASE_FAILED;
                        instr->fail_addr =
                                ((loff_t)page << chip->page_shift);
@@ -2609,7 +2629,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
                /*
                 * If BBT requires refresh, set the BBT rewrite flag to the
-                * page being erased
+                * page being erased.
                 */
                if (bbt_masked_page != 0xffffffff &&
                    (page & BBT_PAGE_MASK) == bbt_masked_page)
@@ -2628,7 +2648,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
                        /*
                         * If BBT requires refresh and BBT-PERCHIP, set the BBT
-                        * page mask to see if this BBT should be rewritten
+                        * page mask to see if this BBT should be rewritten.
                         */
                        if (bbt_masked_page != 0xffffffff &&
                            (chip->bbt_td->options & NAND_BBT_PERCHIP))
@@ -2651,7 +2671,7 @@ erase_exit:
 
        /*
         * If BBT requires refresh and erase was successful, rewrite any
-        * selected bad block tables
+        * selected bad block tables.
         */
        if (bbt_masked_page == 0xffffffff || ret)
                return ret;
@@ -2659,10 +2679,10 @@ erase_exit:
        for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
                if (!rewrite_bbt[chipnr])
                        continue;
-               /* update the BBT for chip */
-               DEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
-                       "(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
-                       rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
+               /* Update the BBT for chip */
+               pr_debug("%s: nand_update_bbt (%d:0x%0llx 0x%0x)\n",
+                               __func__, chipnr, rewrite_bbt[chipnr],
+                               chip->bbt_td->pages[chipnr]);
                nand_update_bbt(mtd, rewrite_bbt[chipnr]);
        }
 
@@ -2672,15 +2692,15 @@ erase_exit:
 
 /**
  * nand_sync - [MTD Interface] sync
- * @mtd:       MTD device structure
+ * @mtd: MTD device structure
  *
- * Sync is actually a wait for chip ready function
+ * Sync is actually a wait for chip ready function.
  */
 static void nand_sync(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
+       pr_debug("%s: called\n", __func__);
 
        /* Grab the lock and see if the device is available */
        nand_get_device(chip, mtd, FL_SYNCING);
@@ -2690,8 +2710,8 @@ static void nand_sync(struct mtd_info *mtd)
 
 /**
  * nand_block_isbad - [MTD Interface] Check if block at offset is bad
- * @mtd:       MTD device structure
- * @offs:      offset relative to mtd start
+ * @mtd: MTD device structure
+ * @offs: offset relative to mtd start
  */
 static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 {
@@ -2704,8 +2724,8 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 
 /**
  * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
- * @mtd:       MTD device structure
- * @ofs:       offset relative to mtd start
+ * @mtd: MTD device structure
+ * @ofs: offset relative to mtd start
  */
 static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
@@ -2714,7 +2734,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
        ret = nand_block_isbad(mtd, ofs);
        if (ret) {
-               /* If it was bad already, return success and do nothing. */
+               /* If it was bad already, return success and do nothing */
                if (ret > 0)
                        return 0;
                return ret;
@@ -2725,7 +2745,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
 /**
  * nand_suspend - [MTD Interface] Suspend the NAND flash
- * @mtd:       MTD device structure
+ * @mtd: MTD device structure
  */
 static int nand_suspend(struct mtd_info *mtd)
 {
@@ -2736,7 +2756,7 @@ static int nand_suspend(struct mtd_info *mtd)
 
 /**
  * nand_resume - [MTD Interface] Resume the NAND flash
- * @mtd:       MTD device structure
+ * @mtd: MTD device structure
  */
 static void nand_resume(struct mtd_info *mtd)
 {
@@ -2745,13 +2765,11 @@ static void nand_resume(struct mtd_info *mtd)
        if (chip->state == FL_PM_SUSPENDED)
                nand_release_device(mtd);
        else
-               printk(KERN_ERR "%s called for a chip which is not "
-                      "in suspended state\n", __func__);
+               pr_err("%s called for a chip which is not in suspended state\n",
+                       __func__);
 }
 
-/*
- * Set default functions
- */
+/* Set default functions */
 static void nand_set_defaults(struct nand_chip *chip, int busw)
 {
        /* check for proper chip_delay setup, set 20us if not */
@@ -2793,23 +2811,21 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 
 }
 
-/*
- * sanitize ONFI strings so we can safely print them
- */
+/* Sanitize ONFI strings so we can safely print them */
 static void sanitize_string(uint8_t *s, size_t len)
 {
        ssize_t i;
 
-       /* null terminate */
+       /* Null terminate */
        s[len - 1] = 0;
 
-       /* remove non printable chars */
+       /* Remove non printable chars */
        for (i = 0; i < len - 1; i++) {
                if (s[i] < ' ' || s[i] > 127)
                        s[i] = '?';
        }
 
-       /* remove trailing spaces */
+       /* Remove trailing spaces */
        strim(s);
 }
 
@@ -2826,28 +2842,28 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
 }
 
 /*
- * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
+ * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
  */
 static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
-                                       int busw)
+                                       int *busw)
 {
        struct nand_onfi_params *p = &chip->onfi_params;
        int i;
        int val;
 
-       /* try ONFI for unknow chip or LP */
+       /* Try ONFI for unknown chip or LP */
        chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
        if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
                chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
                return 0;
 
-       printk(KERN_INFO "ONFI flash detected\n");
+       pr_info("ONFI flash detected\n");
        chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
        for (i = 0; i < 3; i++) {
                chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
                if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
                                le16_to_cpu(p->crc)) {
-                       printk(KERN_INFO "ONFI param page %d valid\n", i);
+                       pr_info("ONFI param page %d valid\n", i);
                        break;
                }
        }
@@ -2855,7 +2871,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
        if (i == 3)
                return 0;
 
-       /* check version */
+       /* Check version */
        val = le16_to_cpu(p->revision);
        if (val & (1 << 5))
                chip->onfi_version = 23;
@@ -2871,8 +2887,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
                chip->onfi_version = 0;
 
        if (!chip->onfi_version) {
-               printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
-                                                               __func__, val);
+               pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
                return 0;
        }
 
@@ -2884,9 +2899,9 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
        mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
        mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
        chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
-       busw = 0;
+       *busw = 0;
        if (le16_to_cpu(p->features) & 1)
-               busw = NAND_BUSWIDTH_16;
+               *busw = NAND_BUSWIDTH_16;
 
        chip->options &= ~NAND_CHIPOPTIONS_MSK;
        chip->options |= (NAND_NO_READRDY |
@@ -2896,7 +2911,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /*
- * Get the flash and manufacturer id and lookup if the type is supported
+ * Get the flash and manufacturer id and lookup if the type is supported.
  */
 static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                                                  struct nand_chip *chip,
@@ -2913,7 +2928,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
        /*
         * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
-        * after power-up
+        * after power-up.
         */
        chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 
@@ -2924,7 +2939,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        *maf_id = chip->read_byte(mtd);
        *dev_id = chip->read_byte(mtd);
 
-       /* Try again to make sure, as some systems the bus-hold or other
+       /*
+        * Try again to make sure, as some systems the bus-hold or other
         * interface concerns can cause random data which looks like a
         * possibly credible NAND flash to appear. If the two results do
         * not match, ignore the device completely.
@@ -2936,9 +2952,9 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                id_data[i] = chip->read_byte(mtd);
 
        if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
-               printk(KERN_INFO "%s: second ID read did not match "
-                      "%02x,%02x against %02x,%02x\n", __func__,
-                      *maf_id, *dev_id, id_data[0], id_data[1]);
+               pr_info("%s: second ID read did not match "
+                       "%02x,%02x against %02x,%02x\n", __func__,
+                       *maf_id, *dev_id, id_data[0], id_data[1]);
                return ERR_PTR(-ENODEV);
        }
 
@@ -2952,7 +2968,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        chip->onfi_version = 0;
        if (!type->name || !type->pagesize) {
                /* Check is chip is ONFI compliant */
-               ret = nand_flash_detect_onfi(mtd, chip, busw);
+               ret = nand_flash_detect_onfi(mtd, chip, &busw);
                if (ret)
                        goto ident_done;
        }
@@ -2973,7 +2989,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        chip->chipsize = (uint64_t)type->chipsize << 20;
 
        if (!type->pagesize && chip->init_size) {
-               /* set the pagesize, oobsize, erasesize by the driver*/
+               /* Set the pagesize, oobsize, erasesize by the driver */
                busw = chip->init_size(mtd, chip, id_data);
        } else if (!type->pagesize) {
                int extid;
@@ -3033,7 +3049,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                }
        } else {
                /*
-                * Old devices have chip data hardcoded in the device id table
+                * Old devices have chip data hardcoded in the device id table.
                 */
                mtd->erasesize = type->erasesize;
                mtd->writesize = type->pagesize;
@@ -3043,7 +3059,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                /*
                 * Check for Spansion/AMD ID + repeating 5th, 6th byte since
                 * some Spansion chips have erasesize that conflicts with size
-                * listed in nand_ids table
+                * listed in nand_ids table.
                 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
                 */
                if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 &&
@@ -3057,15 +3073,16 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        chip->options &= ~NAND_CHIPOPTIONS_MSK;
        chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
 
-       /* Check if chip is a not a samsung device. Do not clear the
-        * options for chips which are not having an extended id.
+       /*
+        * Check if chip is not a Samsung device. Do not clear the
+        * options for chips which do not have an extended id.
         */
        if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
                chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
 ident_done:
 
        /*
-        * Set chip as a default. Board drivers can override it, if necessary
+        * Set chip as a default. Board drivers can override it, if necessary.
         */
        chip->options |= NAND_NO_AUTOINCR;
 
@@ -3077,21 +3094,21 @@ ident_done:
 
        /*
         * Check, if buswidth is correct. Hardware drivers should set
-        * chip correct !
+        * chip correct!
         */
        if (busw != (chip->options & NAND_BUSWIDTH_16)) {
-               printk(KERN_INFO "NAND device: Manufacturer ID:"
-                      " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
-                      *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
-               printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
-                      (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
-                      busw ? 16 : 8);
+               pr_info("NAND device: Manufacturer ID:"
+                       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
+                       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
+               pr_warn("NAND bus width %d instead %d bit\n",
+                          (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
+                          busw ? 16 : 8);
                return ERR_PTR(-EINVAL);
        }
 
        /* Calculate the address shift from the page size */
        chip->page_shift = ffs(mtd->writesize) - 1;
-       /* Convert chipsize to number of pages per chip -1. */
+       /* Convert chipsize to number of pages per chip -1 */
        chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
 
        chip->bbt_erase_shift = chip->phys_erase_shift =
@@ -3121,7 +3138,7 @@ ident_done:
        if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
                        (*maf_id == NAND_MFR_SAMSUNG ||
                         *maf_id == NAND_MFR_HYNIX))
-               chip->options |= NAND_BBT_SCANLASTPAGE;
+               chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
        else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
                                (*maf_id == NAND_MFR_SAMSUNG ||
                                 *maf_id == NAND_MFR_HYNIX ||
@@ -3129,17 +3146,7 @@ ident_done:
                                 *maf_id == NAND_MFR_AMD)) ||
                        (mtd->writesize == 2048 &&
                         *maf_id == NAND_MFR_MICRON))
-               chip->options |= NAND_BBT_SCAN2NDPAGE;
-
-       /*
-        * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
-        */
-       if (!(busw & NAND_BUSWIDTH_16) &&
-                       *maf_id == NAND_MFR_STMICRO &&
-                       mtd->writesize == 2048) {
-               chip->options |= NAND_BBT_SCANBYTE1AND6;
-               chip->badblockpos = 0;
-       }
+               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 
        /* Check for AND chips with 4 page planes */
        if (chip->options & NAND_4PAGE_ARRAY)
@@ -3147,12 +3154,11 @@ ident_done:
        else
                chip->erase_cmd = single_erase_cmd;
 
-       /* Do not replace user supplied command function ! */
+       /* Do not replace user supplied command function! */
        if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
                chip->cmdfunc = nand_command_lp;
 
-       /* TODO onfi flash name */
-       printk(KERN_INFO "NAND device: Manufacturer ID:"
+       pr_info("NAND device: Manufacturer ID:"
                " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
                nand_manuf_ids[maf_idx].name,
                chip->onfi_version ? chip->onfi_params.model : type->name);
@@ -3162,12 +3168,12 @@ ident_done:
 
 /**
  * nand_scan_ident - [NAND Interface] Scan for the NAND device
- * @mtd:            MTD device structure
- * @maxchips:       Number of chips to scan for
- * @table:          Alternative NAND ID table
+ * @mtd: MTD device structure
+ * @maxchips: number of chips to scan for
+ * @table: alternative NAND ID table
  *
- * This is the first phase of the normal nand_scan() function. It
- * reads the flash ID and sets up MTD fields accordingly.
+ * This is the first phase of the normal nand_scan() function. It reads the
+ * flash ID and sets up MTD fields accordingly.
  *
  * The mtd->owner field must be set to the module of the caller.
  */
@@ -3189,7 +3195,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 
        if (IS_ERR(type)) {
                if (!(chip->options & NAND_SCAN_SILENT_NODEV))
-                       printk(KERN_WARNING "No NAND device found.\n");
+                       pr_warn("No NAND device found\n");
                chip->select_chip(mtd, -1);
                return PTR_ERR(type);
        }
@@ -3207,7 +3213,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
                        break;
        }
        if (i > 1)
-               printk(KERN_INFO "%d NAND chips detected\n", i);
+               pr_info("%d NAND chips detected\n", i);
 
        /* Store the number of chips and calc total size for mtd */
        chip->numchips = i;
@@ -3220,11 +3226,11 @@ EXPORT_SYMBOL(nand_scan_ident);
 
 /**
  * nand_scan_tail - [NAND Interface] Scan for the NAND device
- * @mtd:           MTD device structure
+ * @mtd: MTD device structure
  *
- * This is the second phase of the normal nand_scan() function. It
- * fills out all the uninitialized function pointers with the defaults
- * and scans for a bad block table if appropriate.
+ * This is the second phase of the normal nand_scan() function. It fills out
+ * all the uninitialized function pointers with the defaults and scans for a
+ * bad block table if appropriate.
  */
 int nand_scan_tail(struct mtd_info *mtd)
 {
@@ -3240,7 +3246,7 @@ int nand_scan_tail(struct mtd_info *mtd)
        chip->oob_poi = chip->buffers->databuf + mtd->writesize;
 
        /*
-        * If no default placement scheme is given, select an appropriate one
+        * If no default placement scheme is given, select an appropriate one.
         */
        if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
                switch (mtd->oobsize) {
@@ -3257,8 +3263,8 @@ int nand_scan_tail(struct mtd_info *mtd)
                        chip->ecc.layout = &nand_oob_128;
                        break;
                default:
-                       printk(KERN_WARNING "No oob scheme defined for "
-                              "oobsize %d\n", mtd->oobsize);
+                       pr_warn("No oob scheme defined for oobsize %d\n",
+                                  mtd->oobsize);
                        BUG();
                }
        }
@@ -3267,7 +3273,7 @@ int nand_scan_tail(struct mtd_info *mtd)
                chip->write_page = nand_write_page;
 
        /*
-        * check ECC mode, default to software if 3byte/512byte hardware ECC is
+        * Check ECC mode, default to software if 3byte/512byte hardware ECC is
         * selected and we have 256 byte pagesize fallback to software ECC
         */
 
@@ -3276,15 +3282,15 @@ int nand_scan_tail(struct mtd_info *mtd)
                /* Similar to NAND_ECC_HW, but a separate read_page handle */
                if (!chip->ecc.calculate || !chip->ecc.correct ||
                     !chip->ecc.hwctl) {
-                       printk(KERN_WARNING "No ECC functions supplied; "
-                              "Hardware ECC not possible\n");
+                       pr_warn("No ECC functions supplied; "
+                                  "hardware ECC not possible\n");
                        BUG();
                }
                if (!chip->ecc.read_page)
                        chip->ecc.read_page = nand_read_page_hwecc_oob_first;
 
        case NAND_ECC_HW:
-               /* Use standard hwecc read page function ? */
+               /* Use standard hwecc read page function? */
                if (!chip->ecc.read_page)
                        chip->ecc.read_page = nand_read_page_hwecc;
                if (!chip->ecc.write_page)
@@ -3305,11 +3311,11 @@ int nand_scan_tail(struct mtd_info *mtd)
                     chip->ecc.read_page == nand_read_page_hwecc ||
                     !chip->ecc.write_page ||
                     chip->ecc.write_page == nand_write_page_hwecc)) {
-                       printk(KERN_WARNING "No ECC functions supplied; "
-                              "Hardware ECC not possible\n");
+                       pr_warn("No ECC functions supplied; "
+                                  "hardware ECC not possible\n");
                        BUG();
                }
-               /* Use standard syndrome read/write page function ? */
+               /* Use standard syndrome read/write page function? */
                if (!chip->ecc.read_page)
                        chip->ecc.read_page = nand_read_page_syndrome;
                if (!chip->ecc.write_page)
@@ -3325,9 +3331,9 @@ int nand_scan_tail(struct mtd_info *mtd)
 
                if (mtd->writesize >= chip->ecc.size)
                        break;
-               printk(KERN_WARNING "%d byte HW ECC not possible on "
-                      "%d byte page size, fallback to SW ECC\n",
-                      chip->ecc.size, mtd->writesize);
+               pr_warn("%d byte HW ECC not possible on "
+                          "%d byte page size, fallback to SW ECC\n",
+                          chip->ecc.size, mtd->writesize);
                chip->ecc.mode = NAND_ECC_SOFT;
 
        case NAND_ECC_SOFT:
@@ -3347,7 +3353,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 
        case NAND_ECC_SOFT_BCH:
                if (!mtd_nand_has_bch()) {
-                       printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n");
+                       pr_warn("CONFIG_MTD_ECC_BCH not enabled\n");
                        BUG();
                }
                chip->ecc.calculate = nand_bch_calculate_ecc;
@@ -3362,8 +3368,8 @@ int nand_scan_tail(struct mtd_info *mtd)
                /*
                 * Board driver should supply ecc.size and ecc.bytes values to
                 * select how many bits are correctable; see nand_bch_init()
-                * for details.
-                * Otherwise, default to 4 bits for large page devices
+                * for details. Otherwise, default to 4 bits for large page
+                * devices.
                 */
                if (!chip->ecc.size && (mtd->oobsize >= 64)) {
                        chip->ecc.size = 512;
@@ -3374,14 +3380,14 @@ int nand_scan_tail(struct mtd_info *mtd)
                                               chip->ecc.bytes,
                                               &chip->ecc.layout);
                if (!chip->ecc.priv) {
-                       printk(KERN_WARNING "BCH ECC initialization failed!\n");
+                       pr_warn("BCH ECC initialization failed!\n");
                        BUG();
                }
                break;
 
        case NAND_ECC_NONE:
-               printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
-                      "This is not recommended !!\n");
+               pr_warn("NAND_ECC_NONE selected by board driver. "
+                          "This is not recommended!\n");
                chip->ecc.read_page = nand_read_page_raw;
                chip->ecc.write_page = nand_write_page_raw;
                chip->ecc.read_oob = nand_read_oob_std;
@@ -3393,14 +3399,19 @@ int nand_scan_tail(struct mtd_info *mtd)
                break;
 
        default:
-               printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
-                      chip->ecc.mode);
+               pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);
                BUG();
        }
 
+       /* For many systems, the standard OOB write also works for raw */
+       if (!chip->ecc.read_oob_raw)
+               chip->ecc.read_oob_raw = chip->ecc.read_oob;
+       if (!chip->ecc.write_oob_raw)
+               chip->ecc.write_oob_raw = chip->ecc.write_oob;
+
        /*
         * The number of bytes available for a client to place data into
-        * the out of band area
+        * the out of band area.
         */
        chip->ecc.layout->oobavail = 0;
        for (i = 0; chip->ecc.layout->oobfree[i].length
@@ -3411,19 +3422,16 @@ int nand_scan_tail(struct mtd_info *mtd)
 
        /*
         * Set the number of read / write steps for one page depending on ECC
-        * mode
+        * mode.
         */
        chip->ecc.steps = mtd->writesize / chip->ecc.size;
        if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
-               printk(KERN_WARNING "Invalid ecc parameters\n");
+               pr_warn("Invalid ECC parameters\n");
                BUG();
        }
        chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
 
-       /*
-        * Allow subpage writes up to ecc.steps. Not possible for MLC
-        * FLASH.
-        */
+       /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
        if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
            !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
                switch (chip->ecc.steps) {
@@ -3481,9 +3489,11 @@ int nand_scan_tail(struct mtd_info *mtd)
 }
 EXPORT_SYMBOL(nand_scan_tail);
 
-/* is_module_text_address() isn't exported, and it's mostly a pointless
+/*
+ * is_module_text_address() isn't exported, and it's mostly a pointless
  * test if this is a module _anyway_ -- they'd have to try _really_ hard
- * to call us from in-kernel code if the core NAND support is modular. */
+ * to call us from in-kernel code if the core NAND support is modular.
+ */
 #ifdef MODULE
 #define caller_is_module() (1)
 #else
@@ -3493,15 +3503,13 @@ EXPORT_SYMBOL(nand_scan_tail);
 
 /**
  * nand_scan - [NAND Interface] Scan for the NAND device
- * @mtd:       MTD device structure
- * @maxchips:  Number of chips to scan for
- *
- * This fills out all the uninitialized function pointers
- * with the defaults.
- * The flash ID is read and the mtd/chip structures are
- * filled with the appropriate values.
- * The mtd->owner field must be set to the module of the caller
+ * @mtd: MTD device structure
+ * @maxchips: number of chips to scan for
  *
+ * This fills out all the uninitialized function pointers with the defaults.
+ * The flash ID is read and the mtd/chip structures are filled with the
+ * appropriate values. The mtd->owner field must be set to the module of the
+ * caller.
  */
 int nand_scan(struct mtd_info *mtd, int maxchips)
 {
@@ -3509,8 +3517,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
 
        /* Many callers got this wrong, so check for it for a while... */
        if (!mtd->owner && caller_is_module()) {
-               printk(KERN_CRIT "%s called with NULL mtd->owner!\n",
-                               __func__);
+               pr_crit("%s called with NULL mtd->owner!\n", __func__);
                BUG();
        }
 
@@ -3523,8 +3530,8 @@ EXPORT_SYMBOL(nand_scan);
 
 /**
  * nand_release - [NAND Interface] Free resources held by the NAND device
- * @mtd:       MTD device structure
-*/
+ * @mtd: MTD device structure
+ */
 void nand_release(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
index 4165857752ca267de3efef0a917eec42dc484b00..69148ae3bf58aaf806be617894725eb72d1483f1 100644 (file)
@@ -14,7 +14,7 @@
  *
  * When nand_scan_bbt is called, then it tries to find the bad block table
  * depending on the options in the BBT descriptor(s). If no flash based BBT
- * (NAND_USE_FLASH_BBT) is specified then the device is scanned for factory
+ * (NAND_BBT_USE_FLASH) is specified then the device is scanned for factory
  * marked good / bad blocks. This information is used to create a memory BBT.
  * Once a new bad block is discovered then the "factory" information is updated
  * on the device.
@@ -36,9 +36,9 @@
  * The table is marked in the OOB area with an ident pattern and a version
  * number which indicates which of both tables is more up to date. If the NAND
  * controller needs the complete OOB area for the ECC information then the
- * option NAND_USE_FLASH_BBT_NO_OOB should be used: it moves the ident pattern
- * and the version byte into the data area and the OOB area will remain
- * untouched.
+ * option NAND_BBT_NO_OOB should be used (along with NAND_BBT_USE_FLASH, of
+ * course): it moves the ident pattern and the version byte into the data area
+ * and the OOB area will remain untouched.
  *
  * The table uses 2 bits per block
  * 11b:                block is good
@@ -81,17 +81,15 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
 
 /**
  * check_pattern - [GENERIC] check if a pattern is in the buffer
- * @buf:       the buffer to search
- * @len:       the length of buffer to search
- * @paglen:    the pagelength
- * @td:                search pattern descriptor
+ * @buf: the buffer to search
+ * @len: the length of buffer to search
+ * @paglen: the pagelength
+ * @td: search pattern descriptor
  *
- * Check for a pattern at the given place. Used to search bad block
- * tables and good / bad block identifiers.
- * If the SCAN_EMPTY option is set then check, if all bytes except the
- * pattern area contain 0xff
- *
-*/
+ * Check for a pattern at the given place. Used to search bad block tables and
+ * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if
+ * all bytes except the pattern area contain 0xff.
+ */
 static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
 {
        int i, end = 0;
@@ -110,32 +108,8 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
        p += end;
 
        /* Compare the pattern */
-       for (i = 0; i < td->len; i++) {
-               if (p[i] != td->pattern[i])
-                       return -1;
-       }
-
-       /* Check both positions 1 and 6 for pattern? */
-       if (td->options & NAND_BBT_SCANBYTE1AND6) {
-               if (td->options & NAND_BBT_SCANEMPTY) {
-                       p += td->len;
-                       end += NAND_SMALL_BADBLOCK_POS - td->offs;
-                       /* Check region between positions 1 and 6 */
-                       for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len;
-                                       i++) {
-                               if (*p++ != 0xff)
-                                       return -1;
-                       }
-               }
-               else {
-                       p += NAND_SMALL_BADBLOCK_POS - td->offs;
-               }
-               /* Compare the pattern */
-               for (i = 0; i < td->len; i++) {
-                       if (p[i] != td->pattern[i])
-                               return -1;
-               }
-       }
+       if (memcmp(p, td->pattern, td->len))
+               return -1;
 
        if (td->options & NAND_BBT_SCANEMPTY) {
                p += td->len;
@@ -150,14 +124,13 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
 
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
- * @buf:       the buffer to search
- * @td:                search pattern descriptor
- *
- * Check for a pattern at the given place. Used to search bad block
- * tables and good / bad block identifiers. Same as check_pattern, but
- * no optional empty check
+ * @buf: the buffer to search
+ * @td:        search pattern descriptor
  *
-*/
+ * Check for a pattern at the given place. Used to search bad block tables and
+ * good / bad block identifiers. Same as check_pattern, but no optional empty
+ * check.
+ */
 static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
 {
        int i;
@@ -168,21 +141,14 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
                if (p[td->offs + i] != td->pattern[i])
                        return -1;
        }
-       /* Need to check location 1 AND 6? */
-       if (td->options & NAND_BBT_SCANBYTE1AND6) {
-               for (i = 0; i < td->len; i++) {
-                       if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i])
-                               return -1;
-               }
-       }
        return 0;
 }
 
 /**
  * add_marker_len - compute the length of the marker in data area
- * @td:                BBT descriptor used for computation
+ * @td: BBT descriptor used for computation
  *
- * The length will be 0 if the markeris located in OOB area.
+ * The length will be 0 if the marker is located in OOB area.
  */
 static u32 add_marker_len(struct nand_bbt_descr *td)
 {
@@ -199,34 +165,33 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
 
 /**
  * read_bbt - [GENERIC] Read the bad block table starting from page
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @page:      the starting page
- * @num:       the number of bbt descriptors to read
- * @td:                the bbt describtion table
- * @offs:      offset in the memory table
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @page: the starting page
+ * @num: the number of bbt descriptors to read
+ * @td: the bbt describtion table
+ * @offs: offset in the memory table
  *
  * Read the bad block table starting from page.
- *
  */
 static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
                struct nand_bbt_descr *td, int offs)
 {
-       int res, i, j, act = 0;
+       int res, ret = 0, i, j, act = 0;
        struct nand_chip *this = mtd->priv;
        size_t retlen, len, totlen;
        loff_t from;
        int bits = td->options & NAND_BBT_NRBITS_MSK;
-       uint8_t msk = (uint8_t) ((1 << bits) - 1);
+       uint8_t msk = (uint8_t)((1 << bits) - 1);
        u32 marker_len;
        int reserved_block_code = td->reserved_block_code;
 
        totlen = (num * bits) >> 3;
        marker_len = add_marker_len(td);
-       from = ((loff_t) page) << this->page_shift;
+       from = ((loff_t)page) << this->page_shift;
 
        while (totlen) {
-               len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
+               len = min(totlen, (size_t)(1 << this->bbt_erase_shift));
                if (marker_len) {
                        /*
                         * In case the BBT marker is not in the OOB area it
@@ -238,11 +203,18 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
                }
                res = mtd->read(mtd, from, len, &retlen, buf);
                if (res < 0) {
-                       if (retlen != len) {
-                               printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
+                       if (mtd_is_eccerr(res)) {
+                               pr_info("nand_bbt: ECC error in BBT at "
+                                       "0x%012llx\n", from & ~mtd->writesize);
+                               return res;
+                       } else if (mtd_is_bitflip(res)) {
+                               pr_info("nand_bbt: corrected error in BBT at "
+                                       "0x%012llx\n", from & ~mtd->writesize);
+                               ret = res;
+                       } else {
+                               pr_info("nand_bbt: error reading BBT\n");
                                return res;
                        }
-                       printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
                }
 
                /* Analyse data */
@@ -253,17 +225,19 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
                                if (tmp == msk)
                                        continue;
                                if (reserved_block_code && (tmp == reserved_block_code)) {
-                                       printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n",
-                                              (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+                                       pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
+                                                (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
                                        this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
                                        mtd->ecc_stats.bbtblocks++;
                                        continue;
                                }
-                               /* Leave it for now, if its matured we can move this
-                                * message to MTD_DEBUG_LEVEL0 */
-                               printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
-                                      (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
-                               /* Factory marked bad or worn out ? */
+                               /*
+                                * Leave it for now, if it's matured we can
+                                * move this message to pr_debug.
+                                */
+                               pr_info("nand_read_bbt: bad block at 0x%012llx\n",
+                                        (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+                               /* Factory marked bad or worn out? */
                                if (tmp == 0)
                                        this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
                                else
@@ -274,20 +248,20 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
                totlen -= len;
                from += len;
        }
-       return 0;
+       return ret;
 }
 
 /**
  * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @td:                descriptor for the bad block table
- * @chip:      read the table for a specific chip, -1 read all chips.
- *             Applies only if NAND_BBT_PERCHIP option is set
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @chip: read the table for a specific chip, -1 read all chips; applies only if
+ *        NAND_BBT_PERCHIP option is set
  *
- * Read the bad block table for all chips starting at a given page
- * We assume that the bbt bits are in consecutive order.
-*/
+ * Read the bad block table for all chips starting at a given page. We assume
+ * that the bbt bits are in consecutive order.
+ */
 static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
 {
        struct nand_chip *this = mtd->priv;
@@ -313,9 +287,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
        return 0;
 }
 
-/*
- * BBT marker is in the first page, no OOB.
- */
+/* BBT marker is in the first page, no OOB */
 static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
                         struct nand_bbt_descr *td)
 {
@@ -329,35 +301,26 @@ static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
        return mtd->read(mtd, offs, len, &retlen, buf);
 }
 
-/*
- * Scan read raw data from flash
- */
+/* Scan read raw data from flash */
 static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
                         size_t len)
 {
        struct mtd_oob_ops ops;
        int res;
 
-       ops.mode = MTD_OOB_RAW;
+       ops.mode = MTD_OPS_RAW;
        ops.ooboffs = 0;
        ops.ooblen = mtd->oobsize;
 
-
        while (len > 0) {
-               if (len <= mtd->writesize) {
-                       ops.oobbuf = buf + len;
-                       ops.datbuf = buf;
-                       ops.len = len;
-                       return mtd->read_oob(mtd, offs, &ops);
-               } else {
-                       ops.oobbuf = buf + mtd->writesize;
-                       ops.datbuf = buf;
-                       ops.len = mtd->writesize;
-                       res = mtd->read_oob(mtd, offs, &ops);
+               ops.datbuf = buf;
+               ops.len = min(len, (size_t)mtd->writesize);
+               ops.oobbuf = buf + ops.len;
 
-                       if (res)
-                               return res;
-               }
+               res = mtd->read_oob(mtd, offs, &ops);
+
+               if (res)
+                       return res;
 
                buf += mtd->oobsize + mtd->writesize;
                len -= mtd->writesize;
@@ -374,15 +337,13 @@ static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
                return scan_read_raw_oob(mtd, buf, offs, len);
 }
 
-/*
- * Scan write data with oob to flash
- */
+/* Scan write data with oob to flash */
 static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
                          uint8_t *buf, uint8_t *oob)
 {
        struct mtd_oob_ops ops;
 
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = 0;
        ops.ooblen = mtd->oobsize;
        ops.datbuf = buf;
@@ -403,15 +364,14 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
 
 /**
  * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @td:                descriptor for the bad block table
- * @md:                descriptor for the bad block table mirror
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md:        descriptor for the bad block table mirror
  *
- * Read the bad block table(s) for all chips starting at a given page
- * We assume that the bbt bits are in consecutive order.
- *
-*/
+ * Read the bad block table(s) for all chips starting at a given page. We
+ * assume that the bbt bits are in consecutive order.
+ */
 static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
                         struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
@@ -422,8 +382,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
                scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
                              mtd->writesize, td);
                td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
-               printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
-                      td->pages[0], td->version[0]);
+               pr_info("Bad block table at page %d, version 0x%02X\n",
+                        td->pages[0], td->version[0]);
        }
 
        /* Read the mirror version, if available */
@@ -431,15 +391,13 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
                scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
                              mtd->writesize, td);
                md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
-               printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
-                      md->pages[0], md->version[0]);
+               pr_info("Bad block table at page %d, version 0x%02X\n",
+                        md->pages[0], md->version[0]);
        }
        return 1;
 }
 
-/*
- * Scan a given block full
- */
+/* Scan a given block full */
 static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
                           loff_t offs, uint8_t *buf, size_t readlen,
                           int scanlen, int len)
@@ -447,7 +405,8 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
        int ret, j;
 
        ret = scan_read_raw_oob(mtd, buf, offs, readlen);
-       if (ret)
+       /* Ignore ECC errors when checking for BBM */
+       if (ret && !mtd_is_bitflip_or_eccerr(ret))
                return ret;
 
        for (j = 0; j < len; j++, buf += scanlen) {
@@ -457,9 +416,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
        return 0;
 }
 
-/*
- * Scan a given block partially
- */
+/* Scan a given block partially */
 static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
                           loff_t offs, uint8_t *buf, int len)
 {
@@ -470,16 +427,16 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
        ops.oobbuf = buf;
        ops.ooboffs = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
 
        for (j = 0; j < len; j++) {
                /*
-                * Read the full oob until read_oob is fixed to
-                * handle single byte reads for 16 bit
-                * buswidth
+                * Read the full oob until read_oob is fixed to handle single
+                * byte reads for 16 bit buswidth.
                 */
                ret = mtd->read_oob(mtd, offs, &ops);
-               if (ret)
+               /* Ignore ECC errors when checking for BBM */
+               if (ret && !mtd_is_bitflip_or_eccerr(ret))
                        return ret;
 
                if (check_short_pattern(buf, bd))
@@ -492,14 +449,14 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
 
 /**
  * create_bbt - [GENERIC] Create a bad block table by scanning the device
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @bd:                descriptor for the good/bad block search pattern
- * @chip:      create the table for a specific chip, -1 read all chips.
- *             Applies only if NAND_BBT_PERCHIP option is set
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @bd: descriptor for the good/bad block search pattern
+ * @chip: create the table for a specific chip, -1 read all chips; applies only
+ *        if NAND_BBT_PERCHIP option is set
  *
- * Create a bad block table by scanning the device
- * for the given good/bad block identify pattern
+ * Create a bad block table by scanning the device for the given good/bad block
+ * identify pattern.
  */
 static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
        struct nand_bbt_descr *bd, int chip)
@@ -510,7 +467,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
        loff_t from;
        size_t readlen;
 
-       printk(KERN_INFO "Scanning device for bad blocks\n");
+       pr_info("Scanning device for bad blocks\n");
 
        if (bd->options & NAND_BBT_SCANALLPAGES)
                len = 1 << (this->bbt_erase_shift - this->page_shift);
@@ -530,14 +487,16 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
        }
 
        if (chip == -1) {
-               /* Note that numblocks is 2 * (real numblocks) here, see i+=2
-                * below as it makes shifting and masking less painful */
+               /*
+                * Note that numblocks is 2 * (real numblocks) here, see i+=2
+                * below as it makes shifting and masking less painful
+                */
                numblocks = mtd->size >> (this->bbt_erase_shift - 1);
                startblock = 0;
                from = 0;
        } else {
                if (chip >= this->numchips) {
-                       printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
+                       pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
                               chip + 1, this->numchips);
                        return -EINVAL;
                }
@@ -547,7 +506,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
                from = (loff_t)startblock << (this->bbt_erase_shift - 1);
        }
 
-       if (this->options & NAND_BBT_SCANLASTPAGE)
+       if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
                from += mtd->erasesize - (mtd->writesize * len);
 
        for (i = startblock; i < numblocks;) {
@@ -566,8 +525,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
                if (ret) {
                        this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-                       printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n",
-                              i >> 1, (unsigned long long)from);
+                       pr_warn("Bad eraseblock %d at 0x%012llx\n",
+                               i >> 1, (unsigned long long)from);
                        mtd->ecc_stats.badblocks++;
                }
 
@@ -579,20 +538,18 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 /**
  * search_bbt - [GENERIC] scan the device for a specific bad block table
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @td:                descriptor for the bad block table
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
  *
- * Read the bad block table by searching for a given ident pattern.
- * Search is preformed either from the beginning up or from the end of
- * the device downwards. The search starts always at the start of a
- * block.
- * If the option NAND_BBT_PERCHIP is given, each chip is searched
- * for a bbt, which contains the bad block information of this chip.
- * This is necessary to provide support for certain DOC devices.
+ * Read the bad block table by searching for a given ident pattern. Search is
+ * preformed either from the beginning up or from the end of the device
+ * downwards. The search starts always at the start of a block. If the option
+ * NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains
+ * the bad block information of this chip. This is necessary to provide support
+ * for certain DOC devices.
  *
- * The bbt ident pattern resides in the oob area of the first page
- * in a block.
+ * The bbt ident pattern resides in the oob area of the first page in a block.
  */
 static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
 {
@@ -603,7 +560,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        int bbtblocks;
        int blocktopage = this->bbt_erase_shift - this->page_shift;
 
-       /* Search direction top -> down ? */
+       /* Search direction top -> down? */
        if (td->options & NAND_BBT_LASTBLOCK) {
                startblock = (mtd->size >> this->bbt_erase_shift) - 1;
                dir = -1;
@@ -612,7 +569,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
                dir = 1;
        }
 
-       /* Do we have a bbt per chip ? */
+       /* Do we have a bbt per chip? */
        if (td->options & NAND_BBT_PERCHIP) {
                chips = this->numchips;
                bbtblocks = this->chipsize >> this->bbt_erase_shift;
@@ -651,23 +608,23 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        /* Check, if we found a bbt for each requested chip */
        for (i = 0; i < chips; i++) {
                if (td->pages[i] == -1)
-                       printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
+                       pr_warn("Bad block table not found for chip %d\n", i);
                else
-                       printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
-                              td->version[i]);
+                       pr_info("Bad block table found at page %d, version "
+                                "0x%02X\n", td->pages[i], td->version[i]);
        }
        return 0;
 }
 
 /**
  * search_read_bbts - [GENERIC] scan the device for bad block table(s)
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @td:                descriptor for the bad block table
- * @md:                descriptor for the bad block table mirror
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md: descriptor for the bad block table mirror
  *
- * Search and read the bad block table(s)
-*/
+ * Search and read the bad block table(s).
+ */
 static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
        /* Search the primary table */
@@ -683,16 +640,14 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
 
 /**
  * write_bbt - [GENERIC] (Re)write the bad block table
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md: descriptor for the bad block table mirror
+ * @chipsel: selector for a specific chip, -1 for all
  *
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @td:                descriptor for the bad block table
- * @md:                descriptor for the bad block table mirror
- * @chipsel:   selector for a specific chip, -1 for all
- *
- * (Re)write the bad block table
- *
-*/
+ * (Re)write the bad block table.
+ */
 static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
                     struct nand_bbt_descr *td, struct nand_bbt_descr *md,
                     int chipsel)
@@ -711,14 +666,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
        ops.ooblen = mtd->oobsize;
        ops.ooboffs = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
 
        if (!rcode)
                rcode = 0xff;
-       /* Write bad block table per chip rather than per device ? */
+       /* Write bad block table per chip rather than per device? */
        if (td->options & NAND_BBT_PERCHIP) {
                numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
-               /* Full device write or specific chip ? */
+               /* Full device write or specific chip? */
                if (chipsel == -1) {
                        nrchips = this->numchips;
                } else {
@@ -732,8 +687,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 
        /* Loop through the chips */
        for (; chip < nrchips; chip++) {
-
-               /* There was already a version of the table, reuse the page
+               /*
+                * There was already a version of the table, reuse the page
                 * This applies for absolute placement too, as we have the
                 * page nr. in td->pages.
                 */
@@ -742,8 +697,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
                        goto write;
                }
 
-               /* Automatic placement of the bad block table */
-               /* Search direction top -> down ? */
+               /*
+                * Automatic placement of the bad block table. Search direction
+                * top -> down?
+                */
                if (td->options & NAND_BBT_LASTBLOCK) {
                        startblock = numblocks * (chip + 1) - 1;
                        dir = -1;
@@ -767,7 +724,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
                        if (!md || md->pages[chip] != page)
                                goto write;
                }
-               printk(KERN_ERR "No space left to write bad block table\n");
+               pr_err("No space left to write bad block table\n");
                return -ENOSPC;
        write:
 
@@ -792,24 +749,22 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 
                bbtoffs = chip * (numblocks >> 2);
 
-               to = ((loff_t) page) << this->page_shift;
+               to = ((loff_t)page) << this->page_shift;
 
-               /* Must we save the block contents ? */
+               /* Must we save the block contents? */
                if (td->options & NAND_BBT_SAVECONTENT) {
                        /* Make it block aligned */
-                       to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
+                       to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1));
                        len = 1 << this->bbt_erase_shift;
                        res = mtd->read(mtd, to, len, &retlen, buf);
                        if (res < 0) {
                                if (retlen != len) {
-                                       printk(KERN_INFO "nand_bbt: Error "
-                                              "reading block for writing "
-                                              "the bad block table\n");
+                                       pr_info("nand_bbt: error reading block "
+                                               "for writing the bad block table\n");
                                        return res;
                                }
-                               printk(KERN_WARNING "nand_bbt: ECC error "
-                                      "while reading block for writing "
-                                      "bad block table\n");
+                               pr_warn("nand_bbt: ECC error while reading "
+                                       "block for writing bad block table\n");
                        }
                        /* Read oob data */
                        ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
@@ -822,19 +777,19 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
                        pageoffs = page - (int)(to >> this->page_shift);
                        offs = pageoffs << this->page_shift;
                        /* Preset the bbt area with 0xff */
-                       memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
+                       memset(&buf[offs], 0xff, (size_t)(numblocks >> sft));
                        ooboffs = len + (pageoffs * mtd->oobsize);
 
                } else if (td->options & NAND_BBT_NO_OOB) {
                        ooboffs = 0;
                        offs = td->len;
-                       /* the version byte */
+                       /* The version byte */
                        if (td->options & NAND_BBT_VERSION)
                                offs++;
                        /* Calc length */
-                       len = (size_t) (numblocks >> sft);
+                       len = (size_t)(numblocks >> sft);
                        len += offs;
-                       /* Make it page aligned ! */
+                       /* Make it page aligned! */
                        len = ALIGN(len, mtd->writesize);
                        /* Preset the buffer with 0xff */
                        memset(buf, 0xff, len);
@@ -842,8 +797,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
                        memcpy(buf, td->pattern, td->len);
                } else {
                        /* Calc length */
-                       len = (size_t) (numblocks >> sft);
-                       /* Make it page aligned ! */
+                       len = (size_t)(numblocks >> sft);
+                       /* Make it page aligned! */
                        len = ALIGN(len, mtd->writesize);
                        /* Preset the buffer with 0xff */
                        memset(buf, 0xff, len +
@@ -857,13 +812,13 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
                if (td->options & NAND_BBT_VERSION)
                        buf[ooboffs + td->veroffs] = td->version[chip];
 
-               /* walk through the memory table */
+               /* Walk through the memory table */
                for (i = 0; i < numblocks;) {
                        uint8_t dat;
                        dat = this->bbt[bbtoffs + (i >> 2)];
                        for (j = 0; j < 4; j++, i++) {
                                int sftcnt = (i << (3 - sft)) & sftmsk;
-                               /* Do not store the reserved bbt blocks ! */
+                               /* Do not store the reserved bbt blocks! */
                                buf[offs + (i >> sft)] &=
                                        ~(msk[dat & 0x03] << sftcnt);
                                dat >>= 2;
@@ -884,8 +839,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
                if (res < 0)
                        goto outerr;
 
-               printk(KERN_DEBUG "Bad block table written to 0x%012llx, version "
-                      "0x%02X\n", (unsigned long long)to, td->version[chip]);
+               pr_info("Bad block table written to 0x%012llx, version 0x%02X\n",
+                        (unsigned long long)to, td->version[chip]);
 
                /* Mark it as used */
                td->pages[chip] = page;
@@ -893,19 +848,18 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
        return 0;
 
  outerr:
-       printk(KERN_WARNING
-              "nand_bbt: Error while writing bad block table %d\n", res);
+       pr_warn("nand_bbt: error while writing bad block table %d\n", res);
        return res;
 }
 
 /**
  * nand_memory_bbt - [GENERIC] create a memory based bad block table
- * @mtd:       MTD device structure
- * @bd:                descriptor for the good/bad block search pattern
+ * @mtd: MTD device structure
+ * @bd: descriptor for the good/bad block search pattern
  *
- * The function creates a memory based bbt by scanning the device
- * for manufacturer / software marked good / bad blocks
-*/
+ * The function creates a memory based bbt by scanning the device for
+ * manufacturer / software marked good / bad blocks.
+ */
 static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
        struct nand_chip *this = mtd->priv;
@@ -916,25 +870,24 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
 
 /**
  * check_create - [GENERIC] create and write bbt(s) if necessary
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @bd:                descriptor for the good/bad block search pattern
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @bd: descriptor for the good/bad block search pattern
  *
- * The function checks the results of the previous call to read_bbt
- * and creates / updates the bbt(s) if necessary
- * Creation is necessary if no bbt was found for the chip/device
- * Update is necessary if one of the tables is missing or the
- * version nr. of one table is less than the other
-*/
+ * The function checks the results of the previous call to read_bbt and creates
+ * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found
+ * for the chip/device. Update is necessary if one of the tables is missing or
+ * the version nr. of one table is less than the other.
+ */
 static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
 {
-       int i, chips, writeops, chipsel, res;
+       int i, chips, writeops, create, chipsel, res, res2;
        struct nand_chip *this = mtd->priv;
        struct nand_bbt_descr *td = this->bbt_td;
        struct nand_bbt_descr *md = this->bbt_md;
        struct nand_bbt_descr *rd, *rd2;
 
-       /* Do we have a bbt per chip ? */
+       /* Do we have a bbt per chip? */
        if (td->options & NAND_BBT_PERCHIP)
                chips = this->numchips;
        else
@@ -942,86 +895,98 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 
        for (i = 0; i < chips; i++) {
                writeops = 0;
+               create = 0;
                rd = NULL;
                rd2 = NULL;
-               /* Per chip or per device ? */
+               res = res2 = 0;
+               /* Per chip or per device? */
                chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
-               /* Mirrored table available ? */
+               /* Mirrored table available? */
                if (md) {
                        if (td->pages[i] == -1 && md->pages[i] == -1) {
+                               create = 1;
                                writeops = 0x03;
-                               goto create;
-                       }
-
-                       if (td->pages[i] == -1) {
+                       } else if (td->pages[i] == -1) {
                                rd = md;
-                               td->version[i] = md->version[i];
-                               writeops = 1;
-                               goto writecheck;
-                       }
-
-                       if (md->pages[i] == -1) {
+                               writeops = 0x01;
+                       } else if (md->pages[i] == -1) {
                                rd = td;
-                               md->version[i] = td->version[i];
-                               writeops = 2;
-                               goto writecheck;
-                       }
-
-                       if (td->version[i] == md->version[i]) {
+                               writeops = 0x02;
+                       } else if (td->version[i] == md->version[i]) {
                                rd = td;
                                if (!(td->options & NAND_BBT_VERSION))
                                        rd2 = md;
-                               goto writecheck;
-                       }
-
-                       if (((int8_t) (td->version[i] - md->version[i])) > 0) {
+                       } else if (((int8_t)(td->version[i] - md->version[i])) > 0) {
                                rd = td;
-                               md->version[i] = td->version[i];
-                               writeops = 2;
+                               writeops = 0x02;
                        } else {
                                rd = md;
-                               td->version[i] = md->version[i];
-                               writeops = 1;
+                               writeops = 0x01;
                        }
-
-                       goto writecheck;
-
                } else {
                        if (td->pages[i] == -1) {
+                               create = 1;
                                writeops = 0x01;
-                               goto create;
+                       } else {
+                               rd = td;
                        }
-                       rd = td;
-                       goto writecheck;
                }
-       create:
-               /* Create the bad block table by scanning the device ? */
-               if (!(td->options & NAND_BBT_CREATE))
-                       continue;
 
-               /* Create the table in memory by scanning the chip(s) */
-               if (!(this->options & NAND_CREATE_EMPTY_BBT))
-                       create_bbt(mtd, buf, bd, chipsel);
-
-               td->version[i] = 1;
-               if (md)
-                       md->version[i] = 1;
-       writecheck:
-               /* read back first ? */
-               if (rd)
-                       read_abs_bbt(mtd, buf, rd, chipsel);
-               /* If they weren't versioned, read both. */
-               if (rd2)
-                       read_abs_bbt(mtd, buf, rd2, chipsel);
-
-               /* Write the bad block table to the device ? */
+               if (create) {
+                       /* Create the bad block table by scanning the device? */
+                       if (!(td->options & NAND_BBT_CREATE))
+                               continue;
+
+                       /* Create the table in memory by scanning the chip(s) */
+                       if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY))
+                               create_bbt(mtd, buf, bd, chipsel);
+
+                       td->version[i] = 1;
+                       if (md)
+                               md->version[i] = 1;
+               }
+
+               /* Read back first? */
+               if (rd) {
+                       res = read_abs_bbt(mtd, buf, rd, chipsel);
+                       if (mtd_is_eccerr(res)) {
+                               /* Mark table as invalid */
+                               rd->pages[i] = -1;
+                               rd->version[i] = 0;
+                               i--;
+                               continue;
+                       }
+               }
+               /* If they weren't versioned, read both */
+               if (rd2) {
+                       res2 = read_abs_bbt(mtd, buf, rd2, chipsel);
+                       if (mtd_is_eccerr(res2)) {
+                               /* Mark table as invalid */
+                               rd2->pages[i] = -1;
+                               rd2->version[i] = 0;
+                               i--;
+                               continue;
+                       }
+               }
+
+               /* Scrub the flash table(s)? */
+               if (mtd_is_bitflip(res) || mtd_is_bitflip(res2))
+                       writeops = 0x03;
+
+               /* Update version numbers before writing */
+               if (md) {
+                       td->version[i] = max(td->version[i], md->version[i]);
+                       md->version[i] = td->version[i];
+               }
+
+               /* Write the bad block table to the device? */
                if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
                        res = write_bbt(mtd, buf, td, md, chipsel);
                        if (res < 0)
                                return res;
                }
 
-               /* Write the mirror bad block table to the device ? */
+               /* Write the mirror bad block table to the device? */
                if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
                        res = write_bbt(mtd, buf, md, td, chipsel);
                        if (res < 0)
@@ -1033,20 +998,19 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 
 /**
  * mark_bbt_regions - [GENERIC] mark the bad block table regions
- * @mtd:       MTD device structure
- * @td:                bad block table descriptor
+ * @mtd: MTD device structure
+ * @td: bad block table descriptor
  *
- * The bad block table regions are marked as "bad" to prevent
- * accidental erasures / writes. The regions are identified by
- * the mark 0x02.
-*/
+ * The bad block table regions are marked as "bad" to prevent accidental
+ * erasures / writes. The regions are identified by the mark 0x02.
+ */
 static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 {
        struct nand_chip *this = mtd->priv;
        int i, j, chips, block, nrblocks, update;
        uint8_t oldval, newval;
 
-       /* Do we have a bbt per chip ? */
+       /* Do we have a bbt per chip? */
        if (td->options & NAND_BBT_PERCHIP) {
                chips = this->numchips;
                nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
@@ -1083,9 +1047,11 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
                                update = 1;
                        block += 2;
                }
-               /* If we want reserved blocks to be recorded to flash, and some
-                  new ones have been marked, then we need to update the stored
-                  bbts.  This should only happen once. */
+               /*
+                * If we want reserved blocks to be recorded to flash, and some
+                * new ones have been marked, then we need to update the stored
+                * bbts.  This should only happen once.
+                */
                if (update && td->reserved_block_code)
                        nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1));
        }
@@ -1093,8 +1059,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 
 /**
  * verify_bbt_descr - verify the bad block description
- * @mtd:       MTD device structure
- * @bd:                the table to verify
+ * @mtd: MTD device structure
+ * @bd: the table to verify
  *
  * This functions performs a few sanity checks on the bad block description
  * table.
@@ -1112,16 +1078,16 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
        pattern_len = bd->len;
        bits = bd->options & NAND_BBT_NRBITS_MSK;
 
-       BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) &&
-                       !(this->options & NAND_USE_FLASH_BBT));
+       BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) &&
+                       !(this->bbt_options & NAND_BBT_USE_FLASH));
        BUG_ON(!bits);
 
        if (bd->options & NAND_BBT_VERSION)
                pattern_len++;
 
        if (bd->options & NAND_BBT_NO_OOB) {
-               BUG_ON(!(this->options & NAND_USE_FLASH_BBT));
-               BUG_ON(!(this->options & NAND_USE_FLASH_BBT_NO_OOB));
+               BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH));
+               BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB));
                BUG_ON(bd->offs);
                if (bd->options & NAND_BBT_VERSION)
                        BUG_ON(bd->veroffs != bd->len);
@@ -1141,18 +1107,16 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 
 /**
  * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s)
- * @mtd:       MTD device structure
- * @bd:                descriptor for the good/bad block search pattern
- *
- * The function checks, if a bad block table(s) is/are already
- * available. If not it scans the device for manufacturer
- * marked good / bad blocks and writes the bad block table(s) to
- * the selected place.
+ * @mtd: MTD device structure
+ * @bd: descriptor for the good/bad block search pattern
  *
- * The bad block table memory is allocated here. It must be freed
- * by calling the nand_free_bbt function.
+ * The function checks, if a bad block table(s) is/are already available. If
+ * not it scans the device for manufacturer marked good / bad blocks and writes
+ * the bad block table(s) to the selected place.
  *
-*/
+ * The bad block table memory is allocated here. It must be freed by calling
+ * the nand_free_bbt function.
+ */
 int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
        struct nand_chip *this = mtd->priv;
@@ -1162,19 +1126,21 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
        struct nand_bbt_descr *md = this->bbt_md;
 
        len = mtd->size >> (this->bbt_erase_shift + 2);
-       /* Allocate memory (2bit per block) and clear the memory bad block table */
+       /*
+        * Allocate memory (2bit per block) and clear the memory bad block
+        * table.
+        */
        this->bbt = kzalloc(len, GFP_KERNEL);
-       if (!this->bbt) {
-               printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
+       if (!this->bbt)
                return -ENOMEM;
-       }
 
-       /* If no primary table decriptor is given, scan the device
-        * to build a memory based bad block table
+       /*
+        * If no primary table decriptor is given, scan the device to build a
+        * memory based bad block table.
         */
        if (!td) {
                if ((res = nand_memory_bbt(mtd, bd))) {
-                       printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+                       pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
                        kfree(this->bbt);
                        this->bbt = NULL;
                }
@@ -1188,13 +1154,12 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
        len += (len >> this->page_shift) * mtd->oobsize;
        buf = vmalloc(len);
        if (!buf) {
-               printk(KERN_ERR "nand_bbt: Out of memory\n");
                kfree(this->bbt);
                this->bbt = NULL;
                return -ENOMEM;
        }
 
-       /* Is the bbt at a given page ? */
+       /* Is the bbt at a given page? */
        if (td->options & NAND_BBT_ABSPAGE) {
                res = read_abs_bbts(mtd, buf, td, md);
        } else {
@@ -1216,15 +1181,15 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 
 /**
  * nand_update_bbt - [NAND Interface] update bad block table(s)
- * @mtd:       MTD device structure
- * @offs:      the offset of the newly marked block
+ * @mtd: MTD device structure
+ * @offs: the offset of the newly marked block
  *
- * The function updates the bad block table(s)
-*/
+ * The function updates the bad block table(s).
+ */
 int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 {
        struct nand_chip *this = mtd->priv;
-       int len, res = 0, writeops = 0;
+       int len, res = 0;
        int chip, chipsel;
        uint8_t *buf;
        struct nand_bbt_descr *td = this->bbt_td;
@@ -1237,14 +1202,10 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
        len = (1 << this->bbt_erase_shift);
        len += (len >> this->page_shift) * mtd->oobsize;
        buf = kmalloc(len, GFP_KERNEL);
-       if (!buf) {
-               printk(KERN_ERR "nand_update_bbt: Out of memory\n");
+       if (!buf)
                return -ENOMEM;
-       }
-
-       writeops = md != NULL ? 0x03 : 0x01;
 
-       /* Do we have a bbt per chip ? */
+       /* Do we have a bbt per chip? */
        if (td->options & NAND_BBT_PERCHIP) {
                chip = (int)(offs >> this->chip_shift);
                chipsel = chip;
@@ -1257,14 +1218,14 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
        if (md)
                md->version[chip]++;
 
-       /* Write the bad block table to the device ? */
-       if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
+       /* Write the bad block table to the device? */
+       if (td->options & NAND_BBT_WRITE) {
                res = write_bbt(mtd, buf, td, md, chipsel);
                if (res < 0)
                        goto out;
        }
-       /* Write the mirror bad block table to the device ? */
-       if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
+       /* Write the mirror bad block table to the device? */
+       if (md && (md->options & NAND_BBT_WRITE)) {
                res = write_bbt(mtd, buf, md, td, chipsel);
        }
 
@@ -1273,8 +1234,10 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
        return res;
 }
 
-/* Define some generic bad / good block scan pattern which are used
- * while scanning a device for factory marked good / bad blocks. */
+/*
+ * Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks.
+ */
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
 static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
@@ -1286,8 +1249,7 @@ static struct nand_bbt_descr agand_flashbased = {
        .pattern = scan_agand_pattern
 };
 
-/* Generic flash bbt decriptors
-*/
+/* Generic flash bbt descriptors */
 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
 
@@ -1331,31 +1293,27 @@ static struct nand_bbt_descr bbt_mirror_no_bbt_descr = {
        .pattern = mirror_pattern
 };
 
-#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
-               NAND_BBT_SCANBYTE1AND6)
+#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
 /**
- * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
- * @this:      NAND chip to create descriptor for
+ * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure
+ * @this: NAND chip to create descriptor for
  *
  * This function allocates and initializes a nand_bbt_descr for BBM detection
- * based on the properties of "this". The new descriptor is stored in
+ * based on the properties of @this. The new descriptor is stored in
  * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
  * passed to this function.
- *
  */
-static int nand_create_default_bbt_descr(struct nand_chip *this)
+static int nand_create_badblock_pattern(struct nand_chip *this)
 {
        struct nand_bbt_descr *bd;
        if (this->badblock_pattern) {
-               printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
+               pr_warn("Bad block pattern already allocated; not replacing\n");
                return -EINVAL;
        }
        bd = kzalloc(sizeof(*bd), GFP_KERNEL);
-       if (!bd) {
-               printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
+       if (!bd)
                return -ENOMEM;
-       }
-       bd->options = this->options & BBT_SCAN_OPTIONS;
+       bd->options = this->bbt_options & BADBLOCK_SCAN_MASK;
        bd->offs = this->badblockpos;
        bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
        bd->pattern = scan_ff_pattern;
@@ -1366,22 +1324,20 @@ static int nand_create_default_bbt_descr(struct nand_chip *this)
 
 /**
  * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
- * @mtd:       MTD device structure
- *
- * This function selects the default bad block table
- * support for the device and calls the nand_scan_bbt function
+ * @mtd: MTD device structure
  *
-*/
+ * This function selects the default bad block table support for the device and
+ * calls the nand_scan_bbt function.
+ */
 int nand_default_bbt(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
 
-       /* Default for AG-AND. We must use a flash based
-        * bad block table as the devices have factory marked
-        * _good_ blocks. Erasing those blocks leads to loss
-        * of the good / bad information, so we _must_ store
-        * this information in a good / bad table during
-        * startup
+       /*
+        * Default for AG-AND. We must use a flash based bad block table as the
+        * devices have factory marked _good_ blocks. Erasing those blocks
+        * leads to loss of the good / bad information, so we _must_ store this
+        * information in a good / bad table during startup.
         */
        if (this->options & NAND_IS_AND) {
                /* Use the default pattern descriptors */
@@ -1389,15 +1345,15 @@ int nand_default_bbt(struct mtd_info *mtd)
                        this->bbt_td = &bbt_main_descr;
                        this->bbt_md = &bbt_mirror_descr;
                }
-               this->options |= NAND_USE_FLASH_BBT;
+               this->bbt_options |= NAND_BBT_USE_FLASH;
                return nand_scan_bbt(mtd, &agand_flashbased);
        }
 
-       /* Is a flash based bad block table requested ? */
-       if (this->options & NAND_USE_FLASH_BBT) {
+       /* Is a flash based bad block table requested? */
+       if (this->bbt_options & NAND_BBT_USE_FLASH) {
                /* Use the default pattern descriptors */
                if (!this->bbt_td) {
-                       if (this->options & NAND_USE_FLASH_BBT_NO_OOB) {
+                       if (this->bbt_options & NAND_BBT_NO_OOB) {
                                this->bbt_td = &bbt_main_no_bbt_descr;
                                this->bbt_md = &bbt_mirror_no_bbt_descr;
                        } else {
@@ -1411,18 +1367,17 @@ int nand_default_bbt(struct mtd_info *mtd)
        }
 
        if (!this->badblock_pattern)
-               nand_create_default_bbt_descr(this);
+               nand_create_badblock_pattern(this);
 
        return nand_scan_bbt(mtd, this->badblock_pattern);
 }
 
 /**
  * nand_isbad_bbt - [NAND Interface] Check if a block is bad
- * @mtd:       MTD device structure
- * @offs:      offset in the device
- * @allowbbt:  allow access to bad block table region
- *
-*/
+ * @mtd: MTD device structure
+ * @offs: offset in the device
+ * @allowbbt: allow access to bad block table region
+ */
 int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
        struct nand_chip *this = mtd->priv;
@@ -1433,8 +1388,9 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
        block = (int)(offs >> (this->bbt_erase_shift - 1));
        res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
-             (unsigned int)offs, block >> 1, res);
+       pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: "
+                       "(block %d) 0x%02x\n",
+                       (unsigned int)offs, block >> 1, res);
 
        switch ((int)res) {
        case 0x00:
index 0f931e757116fa73b904c2783e46c29cc5a1312b..3803e0bba23be42444b8ab229052478a21bccabd 100644 (file)
@@ -93,8 +93,8 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
                                buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7));
                        /* else error in ecc, no action needed */
 
-                       DEBUG(MTD_DEBUG_LEVEL0, "%s: corrected bitflip %u\n",
-                             __func__, errloc[i]);
+                       pr_debug("%s: corrected bitflip %u\n", __func__,
+                                       errloc[i]);
                }
        } else if (count < 0) {
                printk(KERN_ERR "ecc unrecoverable error\n");
index 271b8e735e8fa1ea21f64a0751d5ab94e147c398..b7cfe0d37121c8bdf78e5147f1cbed41c90b2f0c 100644 (file)
@@ -110,7 +110,7 @@ static const char bitsperbyte[256] = {
 
 /*
  * addressbits is a lookup table to filter out the bits from the xor-ed
- * ecc data that identify the faulty location.
+ * ECC data that identify the faulty location.
  * this is only used for repairing parity
  * see the comments in nand_correct_data for more details
  */
@@ -153,7 +153,7 @@ static const char addressbits[256] = {
  * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
  *                      block
  * @buf:       input buffer with raw data
- * @eccsize:   data bytes per ecc step (256 or 512)
+ * @eccsize:   data bytes per ECC step (256 or 512)
  * @code:      output buffer with ECC
  */
 void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
@@ -348,7 +348,7 @@ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
                rp17 = (par ^ rp16) & 0xff;
 
        /*
-        * Finally calculate the ecc bits.
+        * Finally calculate the ECC bits.
         * Again here it might seem that there are performance optimisations
         * possible, but benchmarks showed that on the system this is developed
         * the code below is the fastest
@@ -436,7 +436,7 @@ EXPORT_SYMBOL(nand_calculate_ecc);
  * @buf:       raw data read from the chip
  * @read_ecc:  ECC from the chip
  * @calc_ecc:  the ECC calculated from raw data
- * @eccsize:   data bytes per ecc step (256 or 512)
+ * @eccsize:   data bytes per ECC step (256 or 512)
  *
  * Detect and correct a 1 bit error for eccsize byte block
  */
@@ -505,7 +505,7 @@ int __nand_correct_data(unsigned char *buf,
        }
        /* count nr of bits; use table lookup, faster than calculating it */
        if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
-               return 1;       /* error in ecc data; no action needed */
+               return 1;       /* error in ECC data; no action needed */
 
        printk(KERN_ERR "uncorrectable error : ");
        return -1;
index 357e8c5252a8c38df3d8ba3885a7fc948b34303c..34c03be7730105c3a26867637700f8c0ade83219 100644 (file)
@@ -2273,9 +2273,9 @@ static int __init ns_init_module(void)
 
        switch (bbt) {
        case 2:
-                chip->options |= NAND_USE_FLASH_BBT_NO_OOB;
+                chip->bbt_options |= NAND_BBT_NO_OOB;
        case 1:
-                chip->options |= NAND_USE_FLASH_BBT;
+                chip->bbt_options |= NAND_BBT_USE_FLASH;
        case 0:
                break;
        default:
index ea2dea8a9c88b6f72e8b59fcd724b085617abfca..ee1713907b92b0684a64de524ca564214699f705 100644 (file)
@@ -42,7 +42,6 @@ struct ndfc_controller {
        struct nand_chip chip;
        int chip_select;
        struct nand_hw_control ndfc_control;
-       struct mtd_partition *parts;
 };
 
 static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
@@ -159,13 +158,9 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 static int ndfc_chip_init(struct ndfc_controller *ndfc,
                          struct device_node *node)
 {
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-       static const char *part_types[] = { "cmdlinepart", NULL };
-#else
-       static const char *part_types[] = { NULL };
-#endif
        struct device_node *flash_np;
        struct nand_chip *chip = &ndfc->chip;
+       struct mtd_part_parser_data ppdata;
        int ret;
 
        chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
@@ -193,6 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
        if (!flash_np)
                return -ENODEV;
 
+       ppdata->of_node = flash_np;
        ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
                        dev_name(&ndfc->ofdev->dev), flash_np->name);
        if (!ndfc->mtd.name) {
@@ -204,18 +200,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
        if (ret)
                goto err;
 
-       ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0);
-       if (ret < 0)
-               goto err;
-
-       if (ret == 0) {
-               ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
-                                             &ndfc->parts);
-               if (ret < 0)
-                       goto err;
-       }
-
-       ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
+       ret = mtd_device_parse_register(&ndfc->mtd, NULL, &ppdata, NULL, 0);
 
 err:
        of_node_put(flash_np);
@@ -288,6 +273,7 @@ static int __devexit ndfc_remove(struct platform_device *ofdev)
        struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
 
        nand_release(&ndfc->mtd);
+       kfree(ndfc->mtd.name);
 
        return 0;
 }
index b6a5c86ab31e922e1ddcf81dc88257012d61ad08..b463ecfb4c1a248713073ab019efed1af2f3d538 100644 (file)
@@ -187,6 +187,7 @@ static int nomadik_nand_remove(struct platform_device *pdev)
                pdata->exit();
 
        if (host) {
+               nand_release(&host->mtd);
                iounmap(host->cmd_va);
                iounmap(host->data_va);
                iounmap(host->addr_va);
index 9c30a0b031715f5d8a26dfd3fb3abbb7418adb6f..fa8faedfad6ee086d15bad4d249b3b0bd0874991 100644 (file)
@@ -339,6 +339,7 @@ static int __devexit nuc900_nand_remove(struct platform_device *pdev)
        struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
        struct resource *res;
 
+       nand_release(&nuc900_nand->mtd);
        iounmap(nuc900_nand->reg);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index ec22a5aab038fd7750c3353137a3a64991ad1ec1..f745f00f3167d455f3d802a0b5ea9dc82a66b617 100644 (file)
@@ -95,8 +95,6 @@
 #define P4e_s(a)       (TF(a & NAND_Ecc_P4e)           << 0)
 #define P4o_s(a)       (TF(a & NAND_Ecc_P4o)           << 1)
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /* oob info generated runtime depending on ecc algorithm and layout selected */
 static struct nand_ecclayout omap_oobinfo;
 /* Define some generic bad / good block scan pattern which are used
@@ -115,7 +113,6 @@ struct omap_nand_info {
        struct nand_hw_control          controller;
        struct omap_nand_platform_data  *pdata;
        struct mtd_info                 mtd;
-       struct mtd_partition            *parts;
        struct nand_chip                nand;
        struct platform_device          *pdev;
 
@@ -745,12 +742,12 @@ static int omap_compare_ecc(u8 *ecc_data1,        /* read from NAND memory */
 
        case 1:
                /* Uncorrectable error */
-               DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
+               pr_debug("ECC UNCORRECTED_ERROR 1\n");
                return -1;
 
        case 11:
                /* UN-Correctable error */
-               DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR B\n");
+               pr_debug("ECC UNCORRECTED_ERROR B\n");
                return -1;
 
        case 12:
@@ -767,8 +764,8 @@ static int omap_compare_ecc(u8 *ecc_data1,  /* read from NAND memory */
 
                find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
 
-               DEBUG(MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at "
-                               "offset: %d, bit: %d\n", find_byte, find_bit);
+               pr_debug("Correcting single bit ECC error at offset: "
+                               "%d, bit: %d\n", find_byte, find_bit);
 
                page_data[find_byte] ^= (1 << find_bit);
 
@@ -780,7 +777,7 @@ static int omap_compare_ecc(u8 *ecc_data1,  /* read from NAND memory */
                            ecc_data2[2] == 0)
                                return 0;
                }
-               DEBUG(MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
+               pr_debug("UNCORRECTED_ERROR default\n");
                return -1;
        }
 }
@@ -1104,13 +1101,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
                goto out_release_mem_region;
        }
 
-       err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
-       if (err > 0)
-               mtd_device_register(&info->mtd, info->parts, err);
-       else if (pdata->parts)
-               mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
-       else
-               mtd_device_register(&info->mtd, NULL, 0);
+       mtd_device_parse_register(&info->mtd, NULL, 0,
+                       pdata->parts, pdata->nr_parts);
 
        platform_set_drvdata(pdev, &info->mtd);
 
index 7794d0680f913b87932ba28d20729e642db382fb..29f505adaf8411581fcbb8d78d09935bef07f36d 100644 (file)
@@ -21,8 +21,6 @@
 #include <mach/hardware.h>
 #include <plat/orion_nand.h>
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
        struct nand_chip *nc = mtd->priv;
@@ -81,8 +79,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
        struct resource *res;
        void __iomem *io_base;
        int ret = 0;
-       struct mtd_partition *partitions = NULL;
-       int num_part = 0;
 
        nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
        if (!nc) {
@@ -132,17 +128,9 @@ static int __init orion_nand_probe(struct platform_device *pdev)
                goto no_dev;
        }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
        mtd->name = "orion_nand";
-       num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0);
-#endif
-       /* If cmdline partitions have been passed, let them be used */
-       if (num_part <= 0) {
-               num_part = board->nr_parts;
-               partitions = board->parts;
-       }
-
-       ret = mtd_device_register(mtd, partitions, num_part);
+       ret = mtd_device_parse_register(mtd, NULL, 0,
+                       board->parts, board->nr_parts);
        if (ret) {
                nand_release(mtd);
                goto no_dev;
index b1aa41b8a4eb6cd0d660d7c38eef8d1be00c0190..a97264ececdbe2278edf20b11a2d072bd38feba4 100644 (file)
@@ -155,7 +155,8 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev)
        chip->ecc.mode = NAND_ECC_SOFT;
 
        /* Enable the following for a flash based bad block table */
-       chip->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
+       chip->options = NAND_NO_AUTOINCR;
+       chip->bbt_options = NAND_BBT_USE_FLASH;
 
        /* Scan to find existence of the device */
        if (nand_scan(pasemi_nand_mtd, 1)) {
index 633c04bf76f6c158aa4029ab83dc6a3d7f3ddca9..ea8e1234e0e25895ed2a731ae1a0225d616468fa 100644 (file)
@@ -21,8 +21,6 @@ struct plat_nand_data {
        struct nand_chip        chip;
        struct mtd_info         mtd;
        void __iomem            *io_base;
-       int                     nr_parts;
-       struct mtd_partition    *parts;
 };
 
 /*
@@ -79,6 +77,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
        data->chip.read_buf = pdata->ctrl.read_buf;
        data->chip.chip_delay = pdata->chip.chip_delay;
        data->chip.options |= pdata->chip.options;
+       data->chip.bbt_options |= pdata->chip.bbt_options;
 
        data->chip.ecc.hwctl = pdata->ctrl.hwcontrol;
        data->chip.ecc.layout = pdata->chip.ecclayout;
@@ -99,23 +98,9 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
                goto out;
        }
 
-       if (pdata->chip.part_probe_types) {
-               err = parse_mtd_partitions(&data->mtd,
-                                       pdata->chip.part_probe_types,
-                                       &data->parts, 0);
-               if (err > 0) {
-                       mtd_device_register(&data->mtd, data->parts, err);
-                       return 0;
-               }
-       }
-       if (pdata->chip.set_parts)
-               pdata->chip.set_parts(data->mtd.size, &pdata->chip);
-       if (pdata->chip.partitions) {
-               data->parts = pdata->chip.partitions;
-               err = mtd_device_register(&data->mtd, data->parts,
-                       pdata->chip.nr_partitions);
-       } else
-               err = mtd_device_register(&data->mtd, NULL, 0);
+       err = mtd_device_parse_register(&data->mtd,
+                       pdata->chip.part_probe_types, 0,
+                       pdata->chip.partitions, pdata->chip.nr_partitions);
 
        if (!err)
                return err;
@@ -145,8 +130,6 @@ static int __devexit plat_nand_remove(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
        nand_release(&data->mtd);
-       if (data->parts && data->parts != pdata->chip.partitions)
-               kfree(data->parts);
        if (pdata->ctrl.remove)
                pdata->ctrl.remove(pdev);
        iounmap(data->io_base);
index 3bbb796b451c7994ab754610c433333308329a88..7e52af51a1986a419e66501bc3286c1e53397651 100644 (file)
@@ -99,8 +99,6 @@ static struct mtd_partition partition_info_evb[] = {
 
 #define NUM_PARTITIONS 1
 
-extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id);
-
 /*
  *     hardware specific access to control-lines
  */
@@ -187,18 +185,12 @@ static int ppchameleonevb_device_ready(struct mtd_info *minfo)
 }
 #endif
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-const char *part_probes_evb[] = { "cmdlinepart", NULL };
-
 /*
  * Main initialization routine
  */
 static int __init ppchameleonevb_init(void)
 {
        struct nand_chip *this;
-       const char *part_type = 0;
-       int mtd_parts_nb = 0;
-       struct mtd_partition *mtd_parts = 0;
        void __iomem *ppchameleon_fio_base;
        void __iomem *ppchameleonevb_fio_base;
 
@@ -281,24 +273,13 @@ static int __init ppchameleonevb_init(void)
 #endif
 
        ppchameleon_mtd->name = "ppchameleon-nand";
-       mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
-       if (mtd_parts_nb > 0)
-               part_type = "command line";
-       else
-               mtd_parts_nb = 0;
-
-       if (mtd_parts_nb == 0) {
-               if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
-                       mtd_parts = partition_info_me;
-               else
-                       mtd_parts = partition_info_hi;
-               mtd_parts_nb = NUM_PARTITIONS;
-               part_type = "static";
-       }
 
        /* Register the partitions */
-       printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-       mtd_device_register(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
+       mtd_device_parse_register(ppchameleon_mtd, NULL, 0,
+                       ppchameleon_mtd->size == NAND_SMALL_SIZE ?
+                               partition_info_me :
+                               partition_info_hi,
+                       NUM_PARTITIONS);
 
  nand_evb_init:
        /****************************
@@ -382,21 +363,13 @@ static int __init ppchameleonevb_init(void)
        }
 
        ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
-       mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
-       if (mtd_parts_nb > 0)
-               part_type = "command line";
-       else
-               mtd_parts_nb = 0;
-
-       if (mtd_parts_nb == 0) {
-               mtd_parts = partition_info_evb;
-               mtd_parts_nb = NUM_PARTITIONS;
-               part_type = "static";
-       }
 
        /* Register the partitions */
-       printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-       mtd_device_register(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb);
+       mtd_device_parse_register(ppchameleonevb_mtd, NULL, 0,
+                       ppchameleon_mtd->size == NAND_SMALL_SIZE ?
+                               partition_info_me :
+                               partition_info_hi,
+                       NUM_PARTITIONS);
 
        /* Return happy */
        return 0;
index 1fb3b3a805818edca37ed2e07bfd8bd90b3d0f4b..9eb7f879969e31a2e5bd987bd27a5295f992516e 100644 (file)
@@ -110,6 +110,7 @@ enum {
 
 enum {
        STATE_IDLE = 0,
+       STATE_PREPARED,
        STATE_CMD_HANDLE,
        STATE_DMA_READING,
        STATE_DMA_WRITING,
@@ -120,21 +121,40 @@ enum {
        STATE_READY,
 };
 
-struct pxa3xx_nand_info {
-       struct nand_chip        nand_chip;
+struct pxa3xx_nand_host {
+       struct nand_chip        chip;
+       struct pxa3xx_nand_cmdset *cmdset;
+       struct mtd_info         *mtd;
+       void                    *info_data;
+
+       /* page size of attached chip */
+       unsigned int            page_size;
+       int                     use_ecc;
+       int                     cs;
 
+       /* calculated from pxa3xx_nand_flash data */
+       unsigned int            col_addr_cycles;
+       unsigned int            row_addr_cycles;
+       size_t                  read_id_bytes;
+
+       /* cached register value */
+       uint32_t                reg_ndcr;
+       uint32_t                ndtr0cs0;
+       uint32_t                ndtr1cs0;
+};
+
+struct pxa3xx_nand_info {
        struct nand_hw_control  controller;
        struct platform_device   *pdev;
-       struct pxa3xx_nand_cmdset *cmdset;
 
        struct clk              *clk;
        void __iomem            *mmio_base;
        unsigned long           mmio_phys;
+       struct completion       cmd_complete;
 
        unsigned int            buf_start;
        unsigned int            buf_count;
 
-       struct mtd_info         *mtd;
        /* DMA information */
        int                     drcmr_dat;
        int                     drcmr_cmd;
@@ -142,44 +162,27 @@ struct pxa3xx_nand_info {
        unsigned char           *data_buff;
        unsigned char           *oob_buff;
        dma_addr_t              data_buff_phys;
-       size_t                  data_buff_size;
        int                     data_dma_ch;
        struct pxa_dma_desc     *data_desc;
        dma_addr_t              data_desc_addr;
 
-       uint32_t                reg_ndcr;
-
-       /* saved column/page_addr during CMD_SEQIN */
-       int                     seqin_column;
-       int                     seqin_page_addr;
-
-       /* relate to the command */
+       struct pxa3xx_nand_host *host[NUM_CHIP_SELECT];
        unsigned int            state;
 
+       int                     cs;
        int                     use_ecc;        /* use HW ECC ? */
        int                     use_dma;        /* use DMA ? */
        int                     is_ready;
 
        unsigned int            page_size;      /* page size of attached chip */
        unsigned int            data_size;      /* data size in FIFO */
+       unsigned int            oob_size;
        int                     retcode;
-       struct completion       cmd_complete;
 
        /* generated NDCBx register values */
        uint32_t                ndcb0;
        uint32_t                ndcb1;
        uint32_t                ndcb2;
-
-       /* timing calcuted from setting */
-       uint32_t                ndtr0cs0;
-       uint32_t                ndtr1cs0;
-
-       /* calculated from pxa3xx_nand_flash data */
-       size_t          oob_size;
-       size_t          read_id_bytes;
-
-       unsigned int    col_addr_cycles;
-       unsigned int    row_addr_cycles;
 };
 
 static int use_dma = 1;
@@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
-const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};
 
 #define NDTR0_tCH(c)   (min((c), 7) << 19)
 #define NDTR0_tCS(c)   (min((c), 7) << 16)
@@ -241,9 +244,10 @@ const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)      (int)((ns) * (clk / 1000000) / 1000)
 
-static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
+static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
                                   const struct pxa3xx_nand_timing *t)
 {
+       struct pxa3xx_nand_info *info = host->info_data;
        unsigned long nand_clk = clk_get_rate(info->clk);
        uint32_t ndtr0, ndtr1;
 
@@ -258,23 +262,24 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
                NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
                NDTR1_tAR(ns2cycle(t->tAR, nand_clk));
 
-       info->ndtr0cs0 = ndtr0;
-       info->ndtr1cs0 = ndtr1;
+       host->ndtr0cs0 = ndtr0;
+       host->ndtr1cs0 = ndtr1;
        nand_writel(info, NDTR0CS0, ndtr0);
        nand_writel(info, NDTR1CS0, ndtr1);
 }
 
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
-       int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+       struct pxa3xx_nand_host *host = info->host[info->cs];
+       int oob_enable = host->reg_ndcr & NDCR_SPARE_EN;
 
-       info->data_size = info->page_size;
+       info->data_size = host->page_size;
        if (!oob_enable) {
                info->oob_size = 0;
                return;
        }
 
-       switch (info->page_size) {
+       switch (host->page_size) {
        case 2048:
                info->oob_size = (info->use_ecc) ? 40 : 64;
                break;
@@ -292,9 +297,10 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
  */
 static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 {
+       struct pxa3xx_nand_host *host = info->host[info->cs];
        uint32_t ndcr;
 
-       ndcr = info->reg_ndcr;
+       ndcr = host->reg_ndcr;
        ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
        ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
        ndcr |= NDCR_ND_RUN;
@@ -359,7 +365,7 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
                                        DIV_ROUND_UP(info->oob_size, 4));
                break;
        default:
-               printk(KERN_ERR "%s: invalid state %d\n", __func__,
+               dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
                                info->state);
                BUG();
        }
@@ -385,7 +391,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
                desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
                break;
        default:
-               printk(KERN_ERR "%s: invalid state %d\n", __func__,
+               dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
                                info->state);
                BUG();
        }
@@ -416,6 +422,15 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
        struct pxa3xx_nand_info *info = devid;
        unsigned int status, is_completed = 0;
+       unsigned int ready, cmd_done;
+
+       if (info->cs == 0) {
+               ready           = NDSR_FLASH_RDY;
+               cmd_done        = NDSR_CS0_CMDD;
+       } else {
+               ready           = NDSR_RDY;
+               cmd_done        = NDSR_CS1_CMDD;
+       }
 
        status = nand_readl(info, NDSR);
 
@@ -437,11 +452,11 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                        handle_data_pio(info);
                }
        }
-       if (status & NDSR_CS0_CMDD) {
+       if (status & cmd_done) {
                info->state = STATE_CMD_DONE;
                is_completed = 1;
        }
-       if (status & NDSR_FLASH_RDY) {
+       if (status & ready) {
                info->is_ready = 1;
                info->state = STATE_READY;
        }
@@ -463,12 +478,6 @@ NORMAL_IRQ_EXIT:
        return IRQ_HANDLED;
 }
 
-static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
-{
-       struct pxa3xx_nand_info *info = mtd->priv;
-       return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0;
-}
-
 static inline int is_buf_blank(uint8_t *buf, size_t len)
 {
        for (; len > 0; len--)
@@ -481,10 +490,12 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                uint16_t column, int page_addr)
 {
        uint16_t cmd;
-       int addr_cycle, exec_cmd, ndcb0;
-       struct mtd_info *mtd = info->mtd;
+       int addr_cycle, exec_cmd;
+       struct pxa3xx_nand_host *host;
+       struct mtd_info *mtd;
 
-       ndcb0 = 0;
+       host = info->host[info->cs];
+       mtd = host->mtd;
        addr_cycle = 0;
        exec_cmd = 1;
 
@@ -495,6 +506,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
        info->use_ecc           = 0;
        info->is_ready          = 0;
        info->retcode           = ERR_NONE;
+       if (info->cs != 0)
+               info->ndcb0 = NDCB0_CSEL;
+       else
+               info->ndcb0 = 0;
 
        switch (command) {
        case NAND_CMD_READ0:
@@ -512,20 +527,19 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                break;
        }
 
-       info->ndcb0 = ndcb0;
-       addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
-                                   + info->col_addr_cycles);
+       addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
+                                   + host->col_addr_cycles);
 
        switch (command) {
        case NAND_CMD_READOOB:
        case NAND_CMD_READ0:
-               cmd = info->cmdset->read1;
+               cmd = host->cmdset->read1;
                if (command == NAND_CMD_READOOB)
                        info->buf_start = mtd->writesize + column;
                else
                        info->buf_start = column;
 
-               if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+               if (unlikely(host->page_size < PAGE_CHUNK_SIZE))
                        info->ndcb0 |= NDCB0_CMD_TYPE(0)
                                        | addr_cycle
                                        | (cmd & NDCB0_CMD1_MASK);
@@ -537,7 +551,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
        case NAND_CMD_SEQIN:
                /* small page addr setting */
-               if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+               if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
                        info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
                                        | (column & 0xFF);
 
@@ -564,7 +578,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                        break;
                }
 
-               cmd = info->cmdset->program;
+               cmd = host->cmdset->program;
                info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
                                | NDCB0_AUTO_RS
                                | NDCB0_ST_ROW_EN
@@ -574,8 +588,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                break;
 
        case NAND_CMD_READID:
-               cmd = info->cmdset->read_id;
-               info->buf_count = info->read_id_bytes;
+               cmd = host->cmdset->read_id;
+               info->buf_count = host->read_id_bytes;
                info->ndcb0 |= NDCB0_CMD_TYPE(3)
                                | NDCB0_ADDR_CYC(1)
                                | cmd;
@@ -583,7 +597,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                info->data_size = 8;
                break;
        case NAND_CMD_STATUS:
-               cmd = info->cmdset->read_status;
+               cmd = host->cmdset->read_status;
                info->buf_count = 1;
                info->ndcb0 |= NDCB0_CMD_TYPE(4)
                                | NDCB0_ADDR_CYC(1)
@@ -593,7 +607,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                break;
 
        case NAND_CMD_ERASE1:
-               cmd = info->cmdset->erase;
+               cmd = host->cmdset->erase;
                info->ndcb0 |= NDCB0_CMD_TYPE(2)
                                | NDCB0_AUTO_RS
                                | NDCB0_ADDR_CYC(3)
@@ -604,7 +618,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
                break;
        case NAND_CMD_RESET:
-               cmd = info->cmdset->reset;
+               cmd = host->cmdset->reset;
                info->ndcb0 |= NDCB0_CMD_TYPE(5)
                                | cmd;
 
@@ -616,8 +630,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
        default:
                exec_cmd = 0;
-               printk(KERN_ERR "pxa3xx-nand: non-supported"
-                       " command %x\n", command);
+               dev_err(&info->pdev->dev, "non-supported command %x\n",
+                               command);
                break;
        }
 
@@ -627,7 +641,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
                                int column, int page_addr)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
        int ret, exec_cmd;
 
        /*
@@ -635,9 +650,21 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
         * "byte" address into a "word" address appropriate
         * for indexing a word-oriented device
         */
-       if (info->reg_ndcr & NDCR_DWIDTH_M)
+       if (host->reg_ndcr & NDCR_DWIDTH_M)
                column /= 2;
 
+       /*
+        * There may be different NAND chip hooked to
+        * different chip select, so check whether
+        * chip select has been changed, if yes, reset the timing
+        */
+       if (info->cs != host->cs) {
+               info->cs = host->cs;
+               nand_writel(info, NDTR0CS0, host->ndtr0cs0);
+               nand_writel(info, NDTR1CS0, host->ndtr1cs0);
+       }
+
+       info->state = STATE_PREPARED;
        exec_cmd = prepare_command_pool(info, command, column, page_addr);
        if (exec_cmd) {
                init_completion(&info->cmd_complete);
@@ -646,12 +673,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
                ret = wait_for_completion_timeout(&info->cmd_complete,
                                CHIP_DELAY_TIMEOUT);
                if (!ret) {
-                       printk(KERN_ERR "Wait time out!!!\n");
+                       dev_err(&info->pdev->dev, "Wait time out!!!\n");
                        /* Stop State Machine for next command cycle */
                        pxa3xx_nand_stop(info);
                }
-               info->state = STATE_IDLE;
        }
+       info->state = STATE_IDLE;
 }
 
 static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
@@ -664,7 +691,8 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
                struct nand_chip *chip, uint8_t *buf, int page)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
 
        chip->read_buf(mtd, buf, mtd->writesize);
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -685,6 +713,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
                 * OOB, ignore such double bit errors
                 */
                if (is_buf_blank(buf, mtd->writesize))
+                       info->retcode = ERR_NONE;
+               else
                        mtd->ecc_stats.failed++;
        }
 
@@ -693,7 +723,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
        char retval = 0xFF;
 
        if (info->buf_start < info->buf_count)
@@ -705,7 +736,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
        u16 retval = 0xFFFF;
 
        if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
@@ -717,7 +749,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
        int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
        memcpy(buf, info->data_buff + info->buf_start, real_len);
@@ -727,7 +760,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
                const uint8_t *buf, int len)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
        int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
        memcpy(info->data_buff + info->buf_start, buf, real_len);
@@ -747,7 +781,8 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
 
 static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
 
        /* pxa3xx_nand_send_command has waited for command complete */
        if (this->state == FL_WRITING || this->state == FL_ERASING) {
@@ -770,54 +805,70 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 {
        struct platform_device *pdev = info->pdev;
        struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+       struct pxa3xx_nand_host *host = info->host[info->cs];
        uint32_t ndcr = 0x0; /* enable all interrupts */
 
-       if (f->page_size != 2048 && f->page_size != 512)
+       if (f->page_size != 2048 && f->page_size != 512) {
+               dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
                return -EINVAL;
+       }
 
-       if (f->flash_width != 16 && f->flash_width != 8)
+       if (f->flash_width != 16 && f->flash_width != 8) {
+               dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
                return -EINVAL;
+       }
 
        /* calculate flash information */
-       info->cmdset = &default_cmdset;
-       info->page_size = f->page_size;
-       info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+       host->cmdset = &default_cmdset;
+       host->page_size = f->page_size;
+       host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
        /* calculate addressing information */
-       info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+       host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
 
        if (f->num_blocks * f->page_per_block > 65536)
-               info->row_addr_cycles = 3;
+               host->row_addr_cycles = 3;
        else
-               info->row_addr_cycles = 2;
+               host->row_addr_cycles = 2;
 
        ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
-       ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+       ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
        ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
        ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
        ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
        ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
 
-       ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
+       ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
        ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
-       info->reg_ndcr = ndcr;
+       host->reg_ndcr = ndcr;
 
-       pxa3xx_nand_set_timing(info, f->timing);
+       pxa3xx_nand_set_timing(host, f->timing);
        return 0;
 }
 
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
+       /*
+        * We set 0 by hard coding here, for we don't support keep_config
+        * when there is more than one chip attached to the controller
+        */
+       struct pxa3xx_nand_host *host = info->host[0];
        uint32_t ndcr = nand_readl(info, NDCR);
-       info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-       /* set info fields needed to read id */
-       info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
-       info->reg_ndcr = ndcr;
-       info->cmdset = &default_cmdset;
 
-       info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
-       info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+       if (ndcr & NDCR_PAGE_SZ) {
+               host->page_size = 2048;
+               host->read_id_bytes = 4;
+       } else {
+               host->page_size = 512;
+               host->read_id_bytes = 2;
+       }
+
+       host->reg_ndcr = ndcr & ~NDCR_INT_MASK;
+       host->cmdset = &default_cmdset;
+
+       host->ndtr0cs0 = nand_readl(info, NDTR0CS0);
+       host->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 
        return 0;
 }
@@ -847,7 +898,6 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
                return -ENOMEM;
        }
 
-       info->data_buff_size = MAX_BUFF_SIZE;
        info->data_desc = (void *)info->data_buff + data_desc_offset;
        info->data_desc_addr = info->data_buff_phys + data_desc_offset;
 
@@ -855,7 +905,7 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
                                pxa3xx_nand_data_dma_irq, info);
        if (info->data_dma_ch < 0) {
                dev_err(&pdev->dev, "failed to request data dma\n");
-               dma_free_coherent(&pdev->dev, info->data_buff_size,
+               dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
                                info->data_buff, info->data_buff_phys);
                return info->data_dma_ch;
        }
@@ -865,24 +915,28 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
 
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-       struct mtd_info *mtd = info->mtd;
-       struct nand_chip *chip = mtd->priv;
-
+       struct mtd_info *mtd;
+       int ret;
+       mtd = info->host[info->cs]->mtd;
        /* use the common timing to make a try */
-       pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
-       chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+       ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+       if (ret)
+               return ret;
+
+       pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
        if (info->is_ready)
-               return 1;
-       else
                return 0;
+
+       return -ENODEV;
 }
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-       struct pxa3xx_nand_info *info = mtd->priv;
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
        struct platform_device *pdev = info->pdev;
        struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
-       struct nand_flash_dev pxa3xx_flash_ids[2] = { {NULL,}, {NULL,} };
+       struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
        const struct pxa3xx_nand_flash *f = NULL;
        struct nand_chip *chip = mtd->priv;
        uint32_t id = -1;
@@ -893,22 +947,20 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
                goto KEEP_CONFIG;
 
        ret = pxa3xx_nand_sensing(info);
-       if (!ret) {
-               kfree(mtd);
-               info->mtd = NULL;
-               printk(KERN_INFO "There is no nand chip on cs 0!\n");
+       if (ret) {
+               dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
+                        info->cs);
 
-               return -EINVAL;
+               return ret;
        }
 
        chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
        id = *((uint16_t *)(info->data_buff));
        if (id != 0)
-               printk(KERN_INFO "Detect a flash id %x\n", id);
+               dev_info(&info->pdev->dev, "Detect a flash id %x\n", id);
        else {
-               kfree(mtd);
-               info->mtd = NULL;
-               printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
+               dev_warn(&info->pdev->dev,
+                        "Read out ID 0, potential timing set wrong!!\n");
 
                return -EINVAL;
        }
@@ -926,14 +978,17 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
        }
 
        if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-               kfree(mtd);
-               info->mtd = NULL;
-               printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+               dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
 
                return -EINVAL;
        }
 
-       pxa3xx_nand_config_flash(info, f);
+       ret = pxa3xx_nand_config_flash(info, f);
+       if (ret) {
+               dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
+               return ret;
+       }
+
        pxa3xx_flash_ids[0].name = f->name;
        pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
        pxa3xx_flash_ids[0].pagesize = f->page_size;
@@ -942,62 +997,78 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
        pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
        if (f->flash_width == 16)
                pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
+       pxa3xx_flash_ids[1].name = NULL;
+       def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-       if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+       chip->ecc.mode = NAND_ECC_HW;
+       chip->ecc.size = host->page_size;
+
+       chip->options = NAND_NO_AUTOINCR;
+       chip->options |= NAND_NO_READRDY;
+       if (host->reg_ndcr & NDCR_DWIDTH_M)
+               chip->options |= NAND_BUSWIDTH_16;
+
+       if (nand_scan_ident(mtd, 1, def))
                return -ENODEV;
        /* calculate addressing information */
-       info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+       if (mtd->writesize >= 2048)
+               host->col_addr_cycles = 2;
+       else
+               host->col_addr_cycles = 1;
+
        info->oob_buff = info->data_buff + mtd->writesize;
        if ((mtd->size >> chip->page_shift) > 65536)
-               info->row_addr_cycles = 3;
+               host->row_addr_cycles = 3;
        else
-               info->row_addr_cycles = 2;
-       mtd->name = mtd_names[0];
-       chip->ecc.mode = NAND_ECC_HW;
-       chip->ecc.size = f->page_size;
-
-       chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
-       chip->options |= NAND_NO_AUTOINCR;
-       chip->options |= NAND_NO_READRDY;
+               host->row_addr_cycles = 2;
 
+       mtd->name = mtd_names[0];
        return nand_scan_tail(mtd);
 }
 
-static
-struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
+static int alloc_nand_resource(struct platform_device *pdev)
 {
+       struct pxa3xx_nand_platform_data *pdata;
        struct pxa3xx_nand_info *info;
+       struct pxa3xx_nand_host *host;
        struct nand_chip *chip;
        struct mtd_info *mtd;
        struct resource *r;
-       int ret, irq;
+       int ret, irq, cs;
 
-       mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
-                       GFP_KERNEL);
-       if (!mtd) {
+       pdata = pdev->dev.platform_data;
+       info = kzalloc(sizeof(*info) + (sizeof(*mtd) +
+                      sizeof(*host)) * pdata->num_cs, GFP_KERNEL);
+       if (!info) {
                dev_err(&pdev->dev, "failed to allocate memory\n");
-               return NULL;
+               return -ENOMEM;
        }
 
-       info = (struct pxa3xx_nand_info *)(&mtd[1]);
-       chip = (struct nand_chip *)(&mtd[1]);
        info->pdev = pdev;
-       info->mtd = mtd;
-       mtd->priv = info;
-       mtd->owner = THIS_MODULE;
-
-       chip->ecc.read_page     = pxa3xx_nand_read_page_hwecc;
-       chip->ecc.write_page    = pxa3xx_nand_write_page_hwecc;
-       chip->controller        = &info->controller;
-       chip->waitfunc          = pxa3xx_nand_waitfunc;
-       chip->select_chip       = pxa3xx_nand_select_chip;
-       chip->dev_ready         = pxa3xx_nand_dev_ready;
-       chip->cmdfunc           = pxa3xx_nand_cmdfunc;
-       chip->read_word         = pxa3xx_nand_read_word;
-       chip->read_byte         = pxa3xx_nand_read_byte;
-       chip->read_buf          = pxa3xx_nand_read_buf;
-       chip->write_buf         = pxa3xx_nand_write_buf;
-       chip->verify_buf        = pxa3xx_nand_verify_buf;
+       for (cs = 0; cs < pdata->num_cs; cs++) {
+               mtd = (struct mtd_info *)((unsigned int)&info[1] +
+                     (sizeof(*mtd) + sizeof(*host)) * cs);
+               chip = (struct nand_chip *)(&mtd[1]);
+               host = (struct pxa3xx_nand_host *)chip;
+               info->host[cs] = host;
+               host->mtd = mtd;
+               host->cs = cs;
+               host->info_data = info;
+               mtd->priv = host;
+               mtd->owner = THIS_MODULE;
+
+               chip->ecc.read_page     = pxa3xx_nand_read_page_hwecc;
+               chip->ecc.write_page    = pxa3xx_nand_write_page_hwecc;
+               chip->controller        = &info->controller;
+               chip->waitfunc          = pxa3xx_nand_waitfunc;
+               chip->select_chip       = pxa3xx_nand_select_chip;
+               chip->cmdfunc           = pxa3xx_nand_cmdfunc;
+               chip->read_word         = pxa3xx_nand_read_word;
+               chip->read_byte         = pxa3xx_nand_read_byte;
+               chip->read_buf          = pxa3xx_nand_read_buf;
+               chip->write_buf         = pxa3xx_nand_write_buf;
+               chip->verify_buf        = pxa3xx_nand_verify_buf;
+       }
 
        spin_lock_init(&chip->controller->lock);
        init_waitqueue_head(&chip->controller->wq);
@@ -1070,13 +1141,13 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, info);
 
-       return info;
+       return 0;
 
 fail_free_buf:
        free_irq(irq, info);
        if (use_dma) {
                pxa_free_dma(info->data_dma_ch);
-               dma_free_coherent(&pdev->dev, info->data_buff_size,
+               dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
                        info->data_buff, info->data_buff_phys);
        } else
                kfree(info->data_buff);
@@ -1088,17 +1159,21 @@ fail_put_clk:
        clk_disable(info->clk);
        clk_put(info->clk);
 fail_free_mtd:
-       kfree(mtd);
-       return NULL;
+       kfree(info);
+       return ret;
 }
 
 static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
        struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-       struct mtd_info *mtd = info->mtd;
+       struct pxa3xx_nand_platform_data *pdata;
        struct resource *r;
-       int irq;
+       int irq, cs;
 
+       if (!info)
+               return 0;
+
+       pdata = pdev->dev.platform_data;
        platform_set_drvdata(pdev, NULL);
 
        irq = platform_get_irq(pdev, 0);
@@ -1106,7 +1181,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
                free_irq(irq, info);
        if (use_dma) {
                pxa_free_dma(info->data_dma_ch);
-               dma_free_writecombine(&pdev->dev, info->data_buff_size,
+               dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
                                info->data_buff, info->data_buff_phys);
        } else
                kfree(info->data_buff);
@@ -1118,10 +1193,9 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
        clk_disable(info->clk);
        clk_put(info->clk);
 
-       if (mtd) {
-               mtd_device_unregister(mtd);
-               kfree(mtd);
-       }
+       for (cs = 0; cs < pdata->num_cs; cs++)
+               nand_release(info->host[cs]->mtd);
+       kfree(info);
        return 0;
 }
 
@@ -1129,6 +1203,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 {
        struct pxa3xx_nand_platform_data *pdata;
        struct pxa3xx_nand_info *info;
+       int ret, cs, probe_success;
 
        pdata = pdev->dev.platform_data;
        if (!pdata) {
@@ -1136,52 +1211,88 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       info = alloc_nand_resource(pdev);
-       if (info == NULL)
-               return -ENOMEM;
-
-       if (pxa3xx_nand_scan(info->mtd)) {
-               dev_err(&pdev->dev, "failed to scan nand\n");
-               pxa3xx_nand_remove(pdev);
-               return -ENODEV;
+       ret = alloc_nand_resource(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "alloc nand resource failed\n");
+               return ret;
        }
 
-       if (mtd_has_cmdlinepart()) {
-               const char *probes[] = { "cmdlinepart", NULL };
-               struct mtd_partition *parts;
-               int nr_parts;
+       info = platform_get_drvdata(pdev);
+       probe_success = 0;
+       for (cs = 0; cs < pdata->num_cs; cs++) {
+               info->cs = cs;
+               ret = pxa3xx_nand_scan(info->host[cs]->mtd);
+               if (ret) {
+                       dev_warn(&pdev->dev, "failed to scan nand at cs %d\n",
+                               cs);
+                       continue;
+               }
 
-               nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+               ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 0,
+                               pdata->parts[cs], pdata->nr_parts[cs]);
+               if (!ret)
+                       probe_success = 1;
+       }
 
-               if (nr_parts)
-                       return mtd_device_register(info->mtd, parts, nr_parts);
+       if (!probe_success) {
+               pxa3xx_nand_remove(pdev);
+               return -ENODEV;
        }
 
-       return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
+       return 0;
 }
 
 #ifdef CONFIG_PM
 static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-       struct mtd_info *mtd = info->mtd;
+       struct pxa3xx_nand_platform_data *pdata;
+       struct mtd_info *mtd;
+       int cs;
 
+       pdata = pdev->dev.platform_data;
        if (info->state) {
                dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
                return -EAGAIN;
        }
 
+       for (cs = 0; cs < pdata->num_cs; cs++) {
+               mtd = info->host[cs]->mtd;
+               mtd->suspend(mtd);
+       }
+
        return 0;
 }
 
 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
        struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-       struct mtd_info *mtd = info->mtd;
+       struct pxa3xx_nand_platform_data *pdata;
+       struct mtd_info *mtd;
+       int cs;
 
-       nand_writel(info, NDTR0CS0, info->ndtr0cs0);
-       nand_writel(info, NDTR1CS0, info->ndtr1cs0);
-       clk_enable(info->clk);
+       pdata = pdev->dev.platform_data;
+       /* We don't want to handle interrupt without calling mtd routine */
+       disable_int(info, NDCR_INT_MASK);
+
+       /*
+        * Directly set the chip select to a invalid value,
+        * then the driver would reset the timing according
+        * to current chip select at the beginning of cmdfunc
+        */
+       info->cs = 0xff;
+
+       /*
+        * As the spec says, the NDSR would be updated to 0x1800 when
+        * doing the nand_clk disable/enable.
+        * To prevent it damaging state machine of the driver, clear
+        * all status before resume
+        */
+       nand_writel(info, NDSR, NDSR_MASK);
+       for (cs = 0; cs < pdata->num_cs; cs++) {
+               mtd = info->host[cs]->mtd;
+               mtd->resume(mtd);
+       }
 
        return 0;
 }
index cae2e013c986fde685be317e1bcaeeff0a8d87e7..f20f393bfda607d84408d5a072898124365f1490 100644 (file)
@@ -1027,7 +1027,7 @@ void r852_shutdown(struct pci_dev *pci_dev)
 }
 
 #ifdef CONFIG_PM
-int r852_suspend(struct device *device)
+static int r852_suspend(struct device *device)
 {
        struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
 
@@ -1048,7 +1048,7 @@ int r852_suspend(struct device *device)
        return 0;
 }
 
-int r852_resume(struct device *device)
+static int r852_resume(struct device *device)
 {
        struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
 
@@ -1092,7 +1092,7 @@ static const struct pci_device_id r852_pci_id_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, r852_pci_id_tbl);
 
-SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume);
+static SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume);
 
 static struct pci_driver r852_pci_driver = {
        .name           = DRV_NAME,
index c9f9127ff7708ee06fae1bd6e159f8e0619f20e5..f309addc2fa0505137f83a7a389bcb74b4fff9e6 100644 (file)
@@ -351,7 +351,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
                return 0;
        }
 
-       /* Read the syndrom pattern from the FPGA and correct the bitorder */
+       /* Read the syndrome pattern from the FPGA and correct the bitorder */
        rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
        for (i = 0; i < 8; i++) {
                ecc[i] = bitrev8(*rs_ecc);
@@ -380,7 +380,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
        /* Let the library code do its magic. */
        res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL);
        if (res > 0) {
-               DEBUG(MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
+               pr_debug("rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
        }
        return res;
 }
@@ -444,7 +444,6 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
                len = mtd->writesize;
                buf = kmalloc(len, GFP_KERNEL);
                if (!buf) {
-                       printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
                        er_stat = 1;
                        goto out;
                }
index 4405468f196b076c6b97fb1366ec8fff55d684a8..868685db6712fa3c18b593b4e9a171707f68f228 100644 (file)
@@ -723,7 +723,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
 
        /* free the common resources */
 
-       if (info->clk != NULL && !IS_ERR(info->clk)) {
+       if (!IS_ERR(info->clk)) {
                s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
                clk_put(info->clk);
        }
@@ -744,26 +744,15 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
        return 0;
 }
 
-const char *part_probes[] = { "cmdlinepart", NULL };
 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
                                      struct s3c2410_nand_mtd *mtd,
                                      struct s3c2410_nand_set *set)
 {
-       struct mtd_partition *part_info;
-       int nr_part = 0;
+       if (set)
+               mtd->mtd.name = set->name;
 
-       if (set == NULL)
-               return mtd_device_register(&mtd->mtd, NULL, 0);
-
-       mtd->mtd.name = set->name;
-       nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0);
-
-       if (nr_part <= 0 && set->nr_partitions > 0) {
-               nr_part = set->nr_partitions;
-               part_info = set->partitions;
-       }
-
-       return mtd_device_register(&mtd->mtd, part_info, nr_part);
+       return mtd_device_parse_register(&mtd->mtd, NULL, 0,
+                       set->partitions, set->nr_partitions);
 }
 
 /**
@@ -880,8 +869,10 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
        /* If you use u-boot BBT creation code, specifying this flag will
         * let the kernel fish out the BBT from the NAND, and also skip the
         * full NAND scan that can take 1/2s or so. Little things... */
-       if (set->flash_bbt)
-               chip->options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
+       if (set->flash_bbt) {
+               chip->bbt_options |= NAND_BBT_USE_FLASH;
+               chip->options |= NAND_SKIP_BBTSCAN;
+       }
 }
 
 /**
index 19e24ed089ea9dd05d1bc9b4ea25dc406d5ede90..619d2a504788b050aa46cc48e0cd13c31588d921 100644 (file)
@@ -103,16 +103,12 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
        return readb(sharpsl->io + ECCCNTR) != 0;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /*
  * Main initialization routine
  */
 static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 {
        struct nand_chip *this;
-       struct mtd_partition *sharpsl_partition_info;
-       int nr_partitions;
        struct resource *r;
        int err = 0;
        struct sharpsl_nand *sharpsl;
@@ -184,14 +180,9 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 
        /* Register the partitions */
        sharpsl->mtd.name = "sharpsl-nand";
-       nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0);
-       if (nr_partitions <= 0) {
-               nr_partitions = data->nr_partitions;
-               sharpsl_partition_info = data->partitions;
-       }
 
-       err = mtd_device_register(&sharpsl->mtd, sharpsl_partition_info,
-                                 nr_partitions);
+       err = mtd_device_parse_register(&sharpsl->mtd, NULL, 0,
+                       data->partitions, data->nr_partitions);
        if (err)
                goto err_add;
 
index 43469715b3fa1f9ef9c34017b13e0768aeef64e2..32ae5af7444f6a28d26e02a7ff6b53efc7e31bde 100644 (file)
@@ -48,7 +48,7 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
        /* As long as this function is called on erase block boundaries
                it will work correctly for 256 byte nand */
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = 0;
        ops.ooblen = mtd->oobsize;
        ops.oobbuf = (void *)&oob;
index ca2d0555729e466b43940043c9d044334f3719d4..0fb24f9c232772dac3c307bff2c7eb7a2d690c5f 100644 (file)
@@ -155,8 +155,6 @@ static int socrates_nand_device_ready(struct mtd_info *mtd)
        return 1;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /*
  * Probe for the NAND device.
  */
@@ -166,8 +164,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
        struct mtd_info *mtd;
        struct nand_chip *nand_chip;
        int res;
-       struct mtd_partition *partitions = NULL;
-       int num_partitions = 0;
+       struct mtd_part_parser_data ppdata;
 
        /* Allocate memory for the device structure (and zero it) */
        host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
@@ -193,6 +190,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
        mtd->name = "socrates_nand";
        mtd->owner = THIS_MODULE;
        mtd->dev.parent = &ofdev->dev;
+       ppdata.of_node = ofdev->dev.of_node;
 
        /*should never be accessed directly */
        nand_chip->IO_ADDR_R = (void *)0xdeadbeef;
@@ -225,30 +223,10 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
                goto out;
        }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-       num_partitions = parse_mtd_partitions(mtd, part_probes,
-                                             &partitions, 0);
-       if (num_partitions < 0) {
-               res = num_partitions;
-               goto release;
-       }
-#endif
-
-       if (num_partitions == 0) {
-               num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-                                                        ofdev->dev.of_node,
-                                                        &partitions);
-               if (num_partitions < 0) {
-                       res = num_partitions;
-                       goto release;
-               }
-       }
-
-       res = mtd_device_register(mtd, partitions, num_partitions);
+       res = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
        if (!res)
                return res;
 
-release:
        nand_release(mtd);
 
 out:
index 11e8371b56834e8b0c79f64fe4d54393be849630..beebd95f76907de7e32102d0dd9a7593be99d0a7 100644 (file)
@@ -121,9 +121,6 @@ struct tmio_nand {
 
 #define mtd_to_tmio(m)                 container_of(m, struct tmio_nand, mtd)
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /*--------------------------------------------------------------------------*/
 
@@ -381,8 +378,6 @@ static int tmio_probe(struct platform_device *dev)
        struct tmio_nand *tmio;
        struct mtd_info *mtd;
        struct nand_chip *nand_chip;
-       struct mtd_partition *parts;
-       int nbparts = 0;
        int retval;
 
        if (data == NULL)
@@ -461,15 +456,9 @@ static int tmio_probe(struct platform_device *dev)
                goto err_scan;
        }
        /* Register the partitions */
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-       nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
-#endif
-       if (nbparts <= 0 && data) {
-               parts = data->partition;
-               nbparts = data->num_partitions;
-       }
-
-       retval = mtd_device_register(mtd, parts, nbparts);
+       retval = mtd_device_parse_register(mtd, NULL, 0,
+                       data ? data->partition : NULL,
+                       data ? data->num_partitions : 0);
        if (!retval)
                return retval;
 
index bfba4e39a6c5cd5866d95b0fd114896489935a62..ace46fdaef58cfb3b51fc9c981e637bb7e0fd2a4 100644 (file)
@@ -74,7 +74,6 @@ struct txx9ndfmc_drvdata {
        unsigned char hold;     /* in gbusclock */
        unsigned char spw;      /* in gbusclock */
        struct nand_hw_control hw_control;
-       struct mtd_partition *parts[MAX_TXX9NDFMC_DEV];
 };
 
 static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
@@ -287,7 +286,6 @@ static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
 static int __init txx9ndfmc_probe(struct platform_device *dev)
 {
        struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
-       static const char *probes[] = { "cmdlinepart", NULL };
        int hold, spw;
        int i;
        struct txx9ndfmc_drvdata *drvdata;
@@ -333,7 +331,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
                struct txx9ndfmc_priv *txx9_priv;
                struct nand_chip *chip;
                struct mtd_info *mtd;
-               int nr_parts;
 
                if (!(plat->ch_mask & (1 << i)))
                        continue;
@@ -393,9 +390,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
                }
                mtd->name = txx9_priv->mtdname;
 
-               nr_parts = parse_mtd_partitions(mtd, probes,
-                                               &drvdata->parts[i], 0);
-               mtd_device_register(mtd, drvdata->parts[i], nr_parts);
+               mtd_device_parse_register(mtd, NULL, 0, NULL, 0);
                drvdata->mtds[i] = mtd;
        }
 
@@ -421,7 +416,6 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev)
                txx9_priv = chip->priv;
 
                nand_release(mtd);
-               kfree(drvdata->parts[i]);
                kfree(txx9_priv->mtdname);
                kfree(txx9_priv);
        }
index b155666acfbe5a1c07ebfa37b1b1ec3c1140d07c..cda77b562ad43da9efd14f1cfb1ab4219583e9d8 100644 (file)
@@ -63,14 +63,12 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
                return;
        }
 
-       DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);
+       pr_debug("NFTL: add_mtd for %s\n", mtd->name);
 
        nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
 
-       if (!nftl) {
-               printk(KERN_WARNING "NFTL: out of memory for data structures\n");
+       if (!nftl)
                return;
-       }
 
        nftl->mbd.mtd = mtd;
        nftl->mbd.devnum = -1;
@@ -132,7 +130,7 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev)
 {
        struct NFTLrecord *nftl = (void *)dev;
 
-       DEBUG(MTD_DEBUG_LEVEL1, "NFTL: remove_dev (i=%d)\n", dev->devnum);
+       pr_debug("NFTL: remove_dev (i=%d)\n", dev->devnum);
 
        del_mtd_blktrans_dev(dev);
        kfree(nftl->ReplUnitTable);
@@ -149,7 +147,7 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
        struct mtd_oob_ops ops;
        int res;
 
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = offs & mask;
        ops.ooblen = len;
        ops.oobbuf = buf;
@@ -170,7 +168,7 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
        struct mtd_oob_ops ops;
        int res;
 
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = offs & mask;
        ops.ooblen = len;
        ops.oobbuf = buf;
@@ -193,7 +191,7 @@ static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
        struct mtd_oob_ops ops;
        int res;
 
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooboffs = offs & mask;
        ops.ooblen = mtd->oobsize;
        ops.oobbuf = oob;
@@ -220,7 +218,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");
+               pr_debug("NFTL_findfreeblock: there are too few free EUNs\n");
                return BLOCK_NIL;
        }
 
@@ -291,8 +289,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
                        if (block == 2) {
                                foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
                                if (foldmark == FOLD_MARK_IN_PROGRESS) {
-                                       DEBUG(MTD_DEBUG_LEVEL1,
-                                             "Write Inhibited on EUN %d\n", thisEUN);
+                                       pr_debug("Write Inhibited on EUN %d\n", thisEUN);
                                        inplace = 0;
                                } else {
                                        /* There's no other reason not to do inplace,
@@ -357,7 +354,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
                        if (BlockLastState[block] != SECTOR_FREE &&
                            BlockMap[block] != BLOCK_NIL &&
                            BlockMap[block] != targetEUN) {
-                               DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, "
+                               pr_debug("Setting inplace to 0. VUC %d, "
                                      "block %d was %x lastEUN, "
                                      "and is in EUN %d (%s) %d\n",
                                      thisVUC, block, BlockLastState[block],
@@ -373,14 +370,14 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
                    pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) &&
                    BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] !=
                    SECTOR_FREE) {
-                       DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. "
+                       pr_debug("Pending write not free in EUN %d. "
                              "Folding out of place.\n", targetEUN);
                        inplace = 0;
                }
        }
 
        if (!inplace) {
-               DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. "
+               pr_debug("Cannot fold Virtual Unit Chain %d in place. "
                      "Trying out-of-place\n", thisVUC);
                /* We need to find a targetEUN to fold into. */
                targetEUN = NFTL_findfreeblock(nftl, 1);
@@ -410,7 +407,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
           and the Erase Unit into which we are supposed to be copying.
           Go for it.
        */
-       DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN);
+       pr_debug("Folding chain %d into unit %d\n", thisVUC, targetEUN);
        for (block = 0; block < nftl->EraseSize / 512 ; block++) {
                unsigned char movebuf[512];
                int ret;
@@ -428,7 +425,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
 
                ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
                                512, &retlen, movebuf);
-               if (ret < 0 && ret != -EUCLEAN) {
+               if (ret < 0 && !mtd_is_bitflip(ret)) {
                        ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block])
                                        + (block * 512), 512, &retlen,
                                        movebuf);
@@ -457,7 +454,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
           has duplicate chains, we need to free one of the chains because it's not necessary any more.
        */
        thisEUN = nftl->EUNtable[thisVUC];
-       DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n");
+       pr_debug("Want to erase\n");
 
        /* For each block in the old chain (except the targetEUN of course),
           free it and make it available for future use */
@@ -570,7 +567,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
                                      (writeEUN * nftl->EraseSize) + blockofs,
                                      8, &retlen, (char *)&bci);
 
-                       DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
+                       pr_debug("Status of block %d in EUN %d is %x\n",
                              block , writeEUN, le16_to_cpu(bci.Status));
 
                        status = bci.Status | bci.Status1;
@@ -623,7 +620,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
                                   but they are reserved for when we're
                                   desperate. Well, now we're desperate.
                                */
-                               DEBUG(MTD_DEBUG_LEVEL1, "Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC);
+                               pr_debug("Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC);
                                writeEUN = NFTL_findfreeblock(nftl, 1);
                        }
                        if (writeEUN == BLOCK_NIL) {
@@ -776,7 +773,7 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
                size_t retlen;
                int res = mtd->read(mtd, ptr, 512, &retlen, buffer);
 
-               if (res < 0 && res != -EUCLEAN)
+               if (res < 0 && !mtd_is_bitflip(res))
                        return -EIO;
        }
        return 0;
index e3cd1ffad2f624c203237068847a5643c3254941..ac4092591aea035068e169900b099ca8121c2185 100644 (file)
@@ -32,7 +32,7 @@
 
 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
  *     various device information of the NFTL partition and Bad Unit Table. Update
- *     the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
+ *     the ReplUnitTable[] table according to the Bad Unit Table. ReplUnitTable[]
  *     is used for management of Erase Unit in other routines in nftl.c and nftlmount.c
  */
 static int find_boot_record(struct NFTLrecord *nftl)
@@ -297,7 +297,7 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int
  *
  * Return: 0 when succeed, -1 on error.
  *
- *  ToDo: 1. Is it neceressary to check_free_sector after erasing ??
+ *  ToDo: 1. Is it necessary to check_free_sector after erasing ??
  */
 int NFTL_formatblock(struct NFTLrecord *nftl, int block)
 {
@@ -337,7 +337,7 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
                nb_erases = le32_to_cpu(uci.WearInfo);
                nb_erases++;
 
-               /* wrap (almost impossible with current flashs) or free block */
+               /* wrap (almost impossible with current flash) or free block */
                if (nb_erases == 0)
                        nb_erases = 1;
 
@@ -363,10 +363,10 @@ fail:
  *     Mark as 'IGNORE' each incorrect sector. This check is only done if the chain
  *     was being folded when NFTL was interrupted.
  *
- *     The check_free_sectors in this function is neceressary. There is a possible
+ *     The check_free_sectors in this function is necessary. There is a possible
  *     situation that after writing the Data area, the Block Control Information is
  *     not updated according (due to power failure or something) which leaves the block
- *     in an umconsistent state. So we have to check if a block is really FREE in this
+ *     in an inconsistent state. So we have to check if a block is really FREE in this
  *     case. */
 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
 {
@@ -428,7 +428,7 @@ static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
 
        for (;;) {
                length++;
-               /* avoid infinite loops, although this is guaranted not to
+               /* avoid infinite loops, although this is guaranteed not to
                   happen because of the previous checks */
                if (length >= nftl->nb_blocks) {
                        printk("nftl: length too long %d !\n", length);
@@ -447,11 +447,11 @@ static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
 /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a
  *     Virtual Unit Chain, i.e. all the units are disconnected.
  *
- *     It is not stricly correct to begin from the first block of the chain because
+ *     It is not strictly correct to begin from the first block of the chain because
  *     if we stop the code, we may see again a valid chain if there was a first_block
  *     flag in a block inside it. But is it really a problem ?
  *
- * FixMe: Figure out what the last statesment means. What if power failure when we are
+ * FixMe: Figure out what the last statement means. What if power failure when we are
  *     in the for (;;) loop formatting blocks ??
  */
 static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
@@ -485,7 +485,7 @@ static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
  *     totally free (only 0xff).
  *
  * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the
- *     following critia:
+ *     following criteria:
  *     1. */
 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
 {
@@ -502,7 +502,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
        erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
        if (erase_mark != ERASE_MARK) {
                /* if no erase mark, the block must be totally free. This is
-                  possible in two cases : empty filsystem or interrupted erase (very unlikely) */
+                  possible in two cases : empty filesystem or interrupted erase (very unlikely) */
                if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0)
                        return -1;
 
@@ -544,7 +544,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
 /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS
  *     to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2
  *     is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted
- *     for some reason. A clean up/check of the VUC is neceressary in this case.
+ *     for some reason. A clean up/check of the VUC is necessary in this case.
  *
  * WARNING: return 0 if read error
  */
@@ -657,7 +657,7 @@ int NFTL_mount(struct NFTLrecord *s)
                                                printk("Block %d: incorrect logical block: %d expected: %d\n",
                                                       block, logical_block, first_logical_block);
                                                /* the chain is incorrect : we must format it,
-                                                  but we need to read it completly */
+                                                  but we need to read it completely */
                                                do_format_chain = 1;
                                        }
                                        if (is_first_block) {
@@ -669,7 +669,7 @@ int NFTL_mount(struct NFTLrecord *s)
                                                        printk("Block %d: incorrectly marked as first block in chain\n",
                                                               block);
                                                        /* the chain is incorrect : we must format it,
-                                                          but we need to read it completly */
+                                                          but we need to read it completely */
                                                        do_format_chain = 1;
                                                } else {
                                                        printk("Block %d: folding in progress - ignoring first block flag\n",
index a996718fa6b06e05607dae1f86bf01a8ff024dd5..64be8f0848b075cdccb647309ff88d12b3fa547d 100644 (file)
 #include <linux/slab.h>
 #include <linux/mtd/partitions.h>
 
-int __devinit of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts)
+static int parse_ofpart_partitions(struct mtd_info *master,
+                                  struct mtd_partition **pparts,
+                                  struct mtd_part_parser_data *data)
 {
+       struct device_node *node;
        const char *partname;
        struct device_node *pp;
        int nr_parts, i;
 
+
+       if (!data)
+               return 0;
+
+       node = data->of_node;
+       if (!node)
+               return 0;
+
        /* First count the subnodes */
        pp = NULL;
        nr_parts = 0;
@@ -69,7 +78,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 
        if (!i) {
                of_node_put(pp);
-               dev_err(dev, "No valid partition found on %s\n", node->full_name);
+               pr_err("No valid partition found on %s\n", node->full_name);
                kfree(*pparts);
                *pparts = NULL;
                return -EINVAL;
@@ -77,6 +86,99 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 
        return nr_parts;
 }
-EXPORT_SYMBOL(of_mtd_parse_partitions);
+
+static struct mtd_part_parser ofpart_parser = {
+       .owner = THIS_MODULE,
+       .parse_fn = parse_ofpart_partitions,
+       .name = "ofpart",
+};
+
+static int parse_ofoldpart_partitions(struct mtd_info *master,
+                                     struct mtd_partition **pparts,
+                                     struct mtd_part_parser_data *data)
+{
+       struct device_node *dp;
+       int i, plen, nr_parts;
+       const struct {
+               __be32 offset, len;
+       } *part;
+       const char *names;
+
+       if (!data)
+               return 0;
+
+       dp = data->of_node;
+       if (!dp)
+               return 0;
+
+       part = of_get_property(dp, "partitions", &plen);
+       if (!part)
+               return 0; /* No partitions found */
+
+       pr_warning("Device tree uses obsolete partition map binding: %s\n",
+                       dp->full_name);
+
+       nr_parts = plen / sizeof(part[0]);
+
+       *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
+       if (!pparts)
+               return -ENOMEM;
+
+       names = of_get_property(dp, "partition-names", &plen);
+
+       for (i = 0; i < nr_parts; i++) {
+               (*pparts)[i].offset = be32_to_cpu(part->offset);
+               (*pparts)[i].size   = be32_to_cpu(part->len) & ~1;
+               /* bit 0 set signifies read only partition */
+               if (be32_to_cpu(part->len) & 1)
+                       (*pparts)[i].mask_flags = MTD_WRITEABLE;
+
+               if (names && (plen > 0)) {
+                       int len = strlen(names) + 1;
+
+                       (*pparts)[i].name = (char *)names;
+                       plen -= len;
+                       names += len;
+               } else {
+                       (*pparts)[i].name = "unnamed";
+               }
+
+               part++;
+       }
+
+       return nr_parts;
+}
+
+static struct mtd_part_parser ofoldpart_parser = {
+       .owner = THIS_MODULE,
+       .parse_fn = parse_ofoldpart_partitions,
+       .name = "ofoldpart",
+};
+
+static int __init ofpart_parser_init(void)
+{
+       int rc;
+       rc = register_mtd_parser(&ofpart_parser);
+       if (rc)
+               goto out;
+
+       rc = register_mtd_parser(&ofoldpart_parser);
+       if (!rc)
+               return 0;
+
+       deregister_mtd_parser(&ofoldpart_parser);
+out:
+       return rc;
+}
+
+module_init(ofpart_parser_init);
 
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
+MODULE_AUTHOR("Vitaly Wool, David Gibson");
+/*
+ * When MTD core cannot find the requested parser, it tries to load the module
+ * with the same name. Since we provide the ofoldpart parser, we should have
+ * the corresponding alias.
+ */
+MODULE_ALIAS("ofoldpart");
index 2d70d354d846b6d36efb334434533445c0e21270..7813095264a56192dbd13c0948da04cfdfd5f82f 100644 (file)
  */
 #define DRIVER_NAME    "onenand-flash"
 
-static const char *part_probes[] = { "cmdlinepart", NULL,  };
-
 struct onenand_info {
        struct mtd_info         mtd;
-       struct mtd_partition    *parts;
        struct onenand_chip     onenand;
 };
 
@@ -73,13 +70,9 @@ static int __devinit generic_onenand_probe(struct platform_device *pdev)
                goto out_iounmap;
        }
 
-       err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
-       if (err > 0)
-               mtd_device_register(&info->mtd, info->parts, err);
-       else if (err <= 0 && pdata && pdata->parts)
-               mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
-       else
-               err = mtd_device_register(&info->mtd, NULL, 0);
+       err = mtd_device_parse_register(&info->mtd, NULL, 0,
+                       pdata ? pdata->parts : NULL,
+                       pdata ? pdata->nr_parts : 0);
 
        platform_set_drvdata(pdev, info);
 
@@ -104,7 +97,6 @@ static int __devexit generic_onenand_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        if (info) {
-               mtd_device_unregister(&info->mtd);
                onenand_release(&info->mtd);
                release_mem_region(res->start, size);
                iounmap(info->onenand.base);
index 6a1d6d9a2df95454fcb7a0212be53fdaf72936b1..7e9ea6852b671d3e1b09f1c259eee49be3ecb968 100644 (file)
@@ -57,7 +57,6 @@ struct omap2_onenand {
        unsigned long phys_base;
        int gpio_irq;
        struct mtd_info mtd;
-       struct mtd_partition *parts;
        struct onenand_chip onenand;
        struct completion irq_done;
        struct completion dma_done;
@@ -67,8 +66,6 @@ struct omap2_onenand {
        struct regulator *regulator;
 };
 
-static const char *part_probes[] = { "cmdlinepart", NULL,  };
-
 static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 {
        struct omap2_onenand *c = data;
@@ -741,6 +738,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
                c->regulator = regulator_get(&pdev->dev, "vonenand");
                if (IS_ERR(c->regulator)) {
                        dev_err(&pdev->dev,  "Failed to get regulator\n");
+                       r = PTR_ERR(c->regulator);
                        goto err_release_dma;
                }
                c->onenand.enable = omap2_onenand_enable;
@@ -753,13 +751,9 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
        if ((r = onenand_scan(&c->mtd, 1)) < 0)
                goto err_release_regulator;
 
-       r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
-       if (r > 0)
-               r = mtd_device_register(&c->mtd, c->parts, r);
-       else if (pdata->parts != NULL)
-               r = mtd_device_register(&c->mtd, pdata->parts, pdata->nr_parts);
-       else
-               r = mtd_device_register(&c->mtd, NULL, 0);
+       r = mtd_device_parse_register(&c->mtd, NULL, 0,
+                       pdata ? pdata->parts : NULL,
+                       pdata ? pdata->nr_parts : 0);
        if (r)
                goto err_release_onenand;
 
@@ -786,7 +780,6 @@ err_release_mem_region:
 err_free_cs:
        gpmc_cs_free(c->gpmc_cs);
 err_kfree:
-       kfree(c->parts);
        kfree(c);
 
        return r;
@@ -809,7 +802,6 @@ 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->parts);
        kfree(c);
 
        return 0;
index ac9e959802a7b113e838ecb8d6e24aee5b7df524..a8394730b4b6fc7e9e84fcdd919e9a09c0b669da 100644 (file)
@@ -1015,7 +1015,7 @@ static void onenand_release_device(struct mtd_info *mtd)
 }
 
 /**
- * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_transfer_auto_oob - [INTERN] oob auto-placement transfer
  * @param mtd          MTD device structure
  * @param buf          destination address
  * @param column       oob offset to read from
@@ -1079,7 +1079,7 @@ static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)
                return status;
 
        /* check if we failed due to uncorrectable error */
-       if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR)
+       if (!mtd_is_eccerr(status) && status != ONENAND_BBT_READ_ECC_ERROR)
                return status;
 
        /* check if address lies in MLC region */
@@ -1122,10 +1122,10 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
        int ret = 0;
        int writesize = this->writesize;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
-             __func__, (unsigned int) from, (int) len);
+       pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+                       (int)len);
 
-       if (ops->mode == MTD_OOB_AUTO)
+       if (ops->mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -1159,7 +1159,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                        if (unlikely(ret))
                                ret = onenand_recover_lsb(mtd, from, ret);
                        onenand_update_bufferram(mtd, from, !ret);
-                       if (ret == -EBADMSG)
+                       if (mtd_is_eccerr(ret))
                                ret = 0;
                        if (ret)
                                break;
@@ -1170,7 +1170,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                        thisooblen = oobsize - oobcolumn;
                        thisooblen = min_t(int, thisooblen, ooblen - oobread);
 
-                       if (ops->mode == MTD_OOB_AUTO)
+                       if (ops->mode == MTD_OPS_AUTO_OOB)
                                onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
                        else
                                this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
@@ -1226,10 +1226,10 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
        int ret = 0, boundary = 0;
        int writesize = this->writesize;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
-                       __func__, (unsigned int) from, (int) len);
+       pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+                       (int)len);
 
-       if (ops->mode == MTD_OOB_AUTO)
+       if (ops->mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -1255,7 +1255,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                        this->command(mtd, ONENAND_CMD_READ, from, writesize);
                        ret = this->wait(mtd, FL_READING);
                        onenand_update_bufferram(mtd, from, !ret);
-                       if (ret == -EBADMSG)
+                       if (mtd_is_eccerr(ret))
                                ret = 0;
                }
        }
@@ -1291,7 +1291,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                        thisooblen = oobsize - oobcolumn;
                        thisooblen = min_t(int, thisooblen, ooblen - oobread);
 
-                       if (ops->mode == MTD_OOB_AUTO)
+                       if (ops->mode == MTD_OPS_AUTO_OOB)
                                onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
                        else
                                this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
@@ -1315,7 +1315,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
                /* Now wait for load */
                ret = this->wait(mtd, FL_READING);
                onenand_update_bufferram(mtd, from, !ret);
-               if (ret == -EBADMSG)
+               if (mtd_is_eccerr(ret))
                        ret = 0;
        }
 
@@ -1351,19 +1351,19 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
        struct mtd_ecc_stats stats;
        int read = 0, thislen, column, oobsize;
        size_t len = ops->ooblen;
-       mtd_oob_mode_t mode = ops->mode;
+       unsigned int mode = ops->mode;
        u_char *buf = ops->oobbuf;
        int ret = 0, readcmd;
 
        from += ops->ooboffs;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
-               __func__, (unsigned int) from, (int) len);
+       pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+                       (int)len);
 
        /* Initialize return length value */
        ops->oobretlen = 0;
 
-       if (mode == MTD_OOB_AUTO)
+       if (mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -1403,13 +1403,13 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
                if (unlikely(ret))
                        ret = onenand_recover_lsb(mtd, from, ret);
 
-               if (ret && ret != -EBADMSG) {
+               if (ret && !mtd_is_eccerr(ret)) {
                        printk(KERN_ERR "%s: read failed = 0x%x\n",
                                __func__, ret);
                        break;
                }
 
-               if (mode == MTD_OOB_AUTO)
+               if (mode == MTD_OPS_AUTO_OOB)
                        onenand_transfer_auto_oob(mtd, buf, column, thislen);
                else
                        this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
@@ -1487,10 +1487,10 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
        int ret;
 
        switch (ops->mode) {
-       case MTD_OOB_PLACE:
-       case MTD_OOB_AUTO:
+       case MTD_OPS_PLACE_OOB:
+       case MTD_OPS_AUTO_OOB:
                break;
-       case MTD_OOB_RAW:
+       case MTD_OPS_RAW:
                /* Not implemented yet */
        default:
                return -EINVAL;
@@ -1576,8 +1576,8 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
        size_t len = ops->ooblen;
        u_char *buf = ops->oobbuf;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %zi\n",
-               __func__, (unsigned int) from, len);
+       pr_debug("%s: from = 0x%08x, len = %zi\n", __func__, (unsigned int)from,
+                       len);
 
        /* Initialize return value */
        ops->oobretlen = 0;
@@ -1750,8 +1750,8 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
        /* Wait for any existing operation to clear */
        onenand_panic_wait(mtd);
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
-               __func__, (unsigned int) to, (int) len);
+       pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+                       (int)len);
 
        /* Initialize retlen, in case of early exit */
        *retlen = 0;
@@ -1821,7 +1821,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
 }
 
 /**
- * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_fill_auto_oob - [INTERN] oob auto-placement transfer
  * @param mtd          MTD device structure
  * @param oob_buf      oob buffer
  * @param buf          source address
@@ -1883,8 +1883,8 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
        u_char *oobbuf;
        int ret = 0, cmd;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
-               __func__, (unsigned int) to, (int) len);
+       pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+                       (int)len);
 
        /* Initialize retlen, in case of early exit */
        ops->retlen = 0;
@@ -1908,7 +1908,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
        if (!len)
                return 0;
 
-       if (ops->mode == MTD_OOB_AUTO)
+       if (ops->mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -1945,7 +1945,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
                                /* We send data to spare ram with oobsize
                                 * to prevent byte access */
                                memset(oobbuf, 0xff, mtd->oobsize);
-                               if (ops->mode == MTD_OOB_AUTO)
+                               if (ops->mode == MTD_OPS_AUTO_OOB)
                                        onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen);
                                else
                                        memcpy(oobbuf + oobcolumn, oob, thisooblen);
@@ -2055,7 +2055,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
 
 
 /**
- * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band
+ * onenand_write_oob_nolock - [INTERN] OneNAND write out-of-band
  * @param mtd          MTD device structure
  * @param to           offset to write to
  * @param len          number of bytes to write
@@ -2074,17 +2074,17 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
        u_char *oobbuf;
        size_t len = ops->ooblen;
        const u_char *buf = ops->oobbuf;
-       mtd_oob_mode_t mode = ops->mode;
+       unsigned int mode = ops->mode;
 
        to += ops->ooboffs;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
-               __func__, (unsigned int) to, (int) len);
+       pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+                       (int)len);
 
        /* Initialize retlen, in case of early exit */
        ops->oobretlen = 0;
 
-       if (mode == MTD_OOB_AUTO)
+       if (mode == MTD_OPS_AUTO_OOB)
                oobsize = this->ecclayout->oobavail;
        else
                oobsize = mtd->oobsize;
@@ -2128,7 +2128,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
                /* We send data to spare ram with oobsize
                 * to prevent byte access */
                memset(oobbuf, 0xff, mtd->oobsize);
-               if (mode == MTD_OOB_AUTO)
+               if (mode == MTD_OPS_AUTO_OOB)
                        onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
                else
                        memcpy(oobbuf + column, buf, thislen);
@@ -2217,10 +2217,10 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
        int ret;
 
        switch (ops->mode) {
-       case MTD_OOB_PLACE:
-       case MTD_OOB_AUTO:
+       case MTD_OPS_PLACE_OOB:
+       case MTD_OPS_AUTO_OOB:
                break;
-       case MTD_OOB_RAW:
+       case MTD_OPS_RAW:
                /* Not implemented yet */
        default:
                return -EINVAL;
@@ -2281,7 +2281,7 @@ static int onenand_multiblock_erase_verify(struct mtd_info *mtd,
 }
 
 /**
- * onenand_multiblock_erase - [Internal] erase block(s) using multiblock erase
+ * onenand_multiblock_erase - [INTERN] erase block(s) using multiblock erase
  * @param mtd          MTD device structure
  * @param instr                erase instruction
  * @param region       erase region
@@ -2397,7 +2397,7 @@ static int onenand_multiblock_erase(struct mtd_info *mtd,
 
 
 /**
- * onenand_block_by_block_erase - [Internal] erase block(s) using regular erase
+ * onenand_block_by_block_erase - [INTERN] erase block(s) using regular erase
  * @param mtd          MTD device structure
  * @param instr                erase instruction
  * @param region       erase region
@@ -2489,8 +2489,9 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
        struct mtd_erase_region_info *region = NULL;
        loff_t region_offset = 0;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: start=0x%012llx, len=%llu\n", __func__,
-             (unsigned long long) instr->addr, (unsigned long long) instr->len);
+       pr_debug("%s: start=0x%012llx, len=%llu\n", __func__,
+                       (unsigned long long)instr->addr,
+                       (unsigned long long)instr->len);
 
        /* Do not allow erase past end of device */
        if (unlikely((len + addr) > mtd->size)) {
@@ -2558,7 +2559,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
  */
 static void onenand_sync(struct mtd_info *mtd)
 {
-       DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
+       pr_debug("%s: called\n", __func__);
 
        /* Grab the lock and see if the device is available */
        onenand_get_device(mtd, FL_SYNCING);
@@ -2602,7 +2603,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
        struct bbm_info *bbm = this->bbm;
        u_char buf[2] = {0, 0};
        struct mtd_oob_ops ops = {
-               .mode = MTD_OOB_PLACE,
+               .mode = MTD_OPS_PLACE_OOB,
                .ooblen = 2,
                .oobbuf = buf,
                .ooboffs = 0,
@@ -2922,7 +2923,7 @@ static int onenand_otp_command(struct mtd_info *mtd, int cmd, loff_t addr,
 }
 
 /**
- * onenand_otp_write_oob_nolock - [Internal] OneNAND write out-of-band, specific to OTP
+ * onenand_otp_write_oob_nolock - [INTERN] OneNAND write out-of-band, specific to OTP
  * @param mtd          MTD device structure
  * @param to           offset to write to
  * @param len          number of bytes to write
@@ -3170,7 +3171,7 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
                this->command(mtd, ONENAND_CMD_RESET, 0, 0);
                this->wait(mtd, FL_RESETING);
        } else {
-               ops.mode = MTD_OOB_PLACE;
+               ops.mode = MTD_OPS_PLACE_OOB;
                ops.ooblen = len;
                ops.oobbuf = buf;
                ops.ooboffs = 0;
@@ -3429,6 +3430,19 @@ static void onenand_check_features(struct mtd_info *mtd)
                else if (numbufs == 1) {
                        this->options |= ONENAND_HAS_4KB_PAGE;
                        this->options |= ONENAND_HAS_CACHE_PROGRAM;
+                       /*
+                        * There are two different 4KiB pagesize chips
+                        * and no way to detect it by H/W config values.
+                        *
+                        * To detect the correct NOP for each chips,
+                        * It should check the version ID as workaround.
+                        *
+                        * Now it has as following
+                        * KFM4G16Q4M has NOP 4 with version ID 0x0131
+                        * KFM4G16Q5M has NOP 1 with versoin ID 0x013e
+                        */
+                       if ((this->version_id & 0xf) == 0xe)
+                               this->options |= ONENAND_HAS_NOP_1;
                }
 
        case ONENAND_DEVICE_DENSITY_2Gb:
@@ -3663,7 +3677,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int
        int i, ret;
        int block;
        struct mtd_oob_ops ops = {
-               .mode = MTD_OOB_PLACE,
+               .mode = MTD_OPS_PLACE_OOB,
                .ooboffs = 0,
                .ooblen = mtd->oobsize,
                .datbuf = NULL,
@@ -4054,6 +4068,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
                        this->ecclayout = &onenand_oob_128;
                        mtd->subpage_sft = 2;
                }
+               if (ONENAND_IS_NOP_1(this))
+                       mtd->subpage_sft = 0;
                break;
        case 64:
                this->ecclayout = &onenand_oob_64;
index b2d7fc5ea25d94a5a669b7a57debfe0fbbbec195..66fe3b7e78515679bae0f8ae75ab9bfb5b509958 100644 (file)
@@ -81,7 +81,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        startblock = 0;
        from = 0;
 
-       ops.mode = MTD_OOB_PLACE;
+       ops.mode = MTD_OPS_PLACE_OOB;
        ops.ooblen = readlen;
        ops.oobbuf = buf;
        ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
@@ -154,7 +154,7 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
        block = (int) (onenand_block(this, offs) << 1);
        res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
-       DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+       pr_debug("onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
                (unsigned int) offs, block >> 1, res);
 
        switch ((int) res) {
@@ -189,10 +189,8 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
        len = this->chipsize >> (this->erase_shift + 2);
        /* Allocate memory (2bit per block) and clear the memory bad block table */
        bbm->bbt = kzalloc(len, GFP_KERNEL);
-       if (!bbm->bbt) {
-               printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
+       if (!bbm->bbt)
                return -ENOMEM;
-       }
 
        /* Set the bad block position */
        bbm->badblockpos = ONENAND_BADBLOCK_POS;
index 3306b5b3c736b82206cd1e56ee5afd9e11bd5dfa..5474547eafc2fc271b2000bcf5c146a18b4a8372 100644 (file)
@@ -147,7 +147,6 @@ struct s3c_onenand {
        struct resource *dma_res;
        unsigned long   phys_base;
        struct completion       complete;
-       struct mtd_partition *parts;
 };
 
 #define CMD_MAP_00(dev, addr)          (dev->cmd_map(MAP_00, ((addr) << 1)))
@@ -157,8 +156,6 @@ struct s3c_onenand {
 
 static struct s3c_onenand *onenand;
 
-static const char *part_probes[] = { "cmdlinepart", NULL, };
-
 static inline int s3c_read_reg(int offset)
 {
        return readl(onenand->base + offset);
@@ -1017,13 +1014,9 @@ static int s3c_onenand_probe(struct platform_device *pdev)
        if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
                dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
 
-       err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0);
-       if (err > 0)
-               mtd_device_register(mtd, onenand->parts, err);
-       else if (err <= 0 && pdata && pdata->parts)
-               mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
-       else
-               err = mtd_device_register(mtd, NULL, 0);
+       err = mtd_device_parse_register(mtd, NULL, 0,
+                                       pdata ? pdata->parts : NULL,
+                                       pdata ? pdata->nr_parts : 0);
 
        platform_set_drvdata(pdev, mtd);
 
index 84b4dda023f4e1d2b870f25b779d6090ca30e8a5..e366b1d84eade1685821dcf5021427e993656842 100644 (file)
@@ -57,8 +57,8 @@ static inline int redboot_checksum(struct fis_image_desc *img)
 }
 
 static int parse_redboot_partitions(struct mtd_info *master,
-                             struct mtd_partition **pparts,
-                             unsigned long fis_origin)
+                                   struct mtd_partition **pparts,
+                                   struct mtd_part_parser_data *data)
 {
        int nrparts = 0;
        struct fis_image_desc *buf;
@@ -198,11 +198,10 @@ static int parse_redboot_partitions(struct mtd_info *master,
                        goto out;
                }
                new_fl->img = &buf[i];
-                if (fis_origin) {
-                        buf[i].flash_base -= fis_origin;
-                } else {
-                        buf[i].flash_base &= master->size-1;
-                }
+               if (data && data->origin)
+                       buf[i].flash_base -= data->origin;
+               else
+                       buf[i].flash_base &= master->size-1;
 
                /* I'm sure the JFFS2 code has done me permanent damage.
                 * I now think the following is _normal_
@@ -298,6 +297,9 @@ static struct mtd_part_parser redboot_parser = {
        .name = "RedBoot",
 };
 
+/* mtd parsers will request the module by parser name */
+MODULE_ALIAS("RedBoot");
+
 static int __init redboot_parser_init(void)
 {
        return register_mtd_parser(&redboot_parser);
index ed3d6cd2c6dca216e097bfd5491544283be5ac11..fddb714e323cf3ea577b40c32e4abbb2aced5f29 100644 (file)
@@ -34,7 +34,7 @@ module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level (0-2)");
 
 
-/* ------------------- sysfs attributtes ---------------------------------- */
+/* ------------------- sysfs attributes ---------------------------------- */
 struct sm_sysfs_attribute {
        struct device_attribute dev_attr;
        char *data;
@@ -138,7 +138,7 @@ static int sm_get_lba(uint8_t *lba)
        if ((lba[0] & 0xF8) != 0x10)
                return -2;
 
-       /* check parity - endianess doesn't matter */
+       /* check parity - endianness doesn't matter */
        if (hweight16(*(uint16_t *)lba) & 1)
                return -2;
 
@@ -147,7 +147,7 @@ static int sm_get_lba(uint8_t *lba)
 
 
 /*
- * Read LBA asscociated with block
+ * Read LBA associated with block
  * returns -1, if block is erased
  * returns -2 if error happens
  */
@@ -252,11 +252,11 @@ static int sm_read_sector(struct sm_ftl *ftl,
                return 0;
        }
 
-       /* User might not need the oob, but we do for data vertification */
+       /* User might not need the oob, but we do for data verification */
        if (!oob)
                oob = &tmp_oob;
 
-       ops.mode = ftl->smallpagenand ? MTD_OOB_RAW : MTD_OOB_PLACE;
+       ops.mode = ftl->smallpagenand ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB;
        ops.ooboffs = 0;
        ops.ooblen = SM_OOB_SIZE;
        ops.oobbuf = (void *)oob;
@@ -276,12 +276,12 @@ again:
                        return ret;
        }
 
-       /* Unfortunelly, oob read will _always_ succeed,
+       /* Unfortunately, oob read will _always_ succeed,
                despite card removal..... */
        ret = mtd->read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops);
 
        /* Test for unknown errors */
-       if (ret != 0 && ret != -EUCLEAN && ret != -EBADMSG) {
+       if (ret != 0 && !mtd_is_bitflip_or_eccerr(ret)) {
                dbg("read of block %d at zone %d, failed due to error (%d)",
                        block, zone, ret);
                goto again;
@@ -306,7 +306,7 @@ again:
        }
 
        /* Test ECC*/
-       if (ret == -EBADMSG ||
+       if (mtd_is_eccerr(ret) ||
                (ftl->smallpagenand && sm_correct_sector(buffer, oob))) {
 
                dbg("read of block %d at zone %d, failed due to ECC error",
@@ -336,7 +336,7 @@ static int sm_write_sector(struct sm_ftl *ftl,
        if (ftl->unstable)
                return -EIO;
 
-       ops.mode = ftl->smallpagenand ? MTD_OOB_RAW : MTD_OOB_PLACE;
+       ops.mode = ftl->smallpagenand ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB;
        ops.len = SM_SECTOR_SIZE;
        ops.datbuf = buffer;
        ops.ooboffs = 0;
@@ -447,14 +447,14 @@ static void sm_mark_block_bad(struct sm_ftl *ftl, int zone, int block)
 
        /* We aren't checking the return value, because we don't care */
        /* This also fails on fake xD cards, but I guess these won't expose
-               any bad blocks till fail completly */
+               any bad blocks till fail completely */
        for (boffset = 0; boffset < ftl->block_size; boffset += SM_SECTOR_SIZE)
                sm_write_sector(ftl, zone, block, boffset, NULL, &oob);
 }
 
 /*
  * Erase a block within a zone
- * If erase succedes, it updates free block fifo, otherwise marks block as bad
+ * If erase succeeds, it updates free block fifo, otherwise marks block as bad
  */
 static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block,
                          int put_free)
@@ -510,7 +510,7 @@ static void sm_erase_callback(struct erase_info *self)
        complete(&ftl->erase_completion);
 }
 
-/* Throughtly test that block is valid. */
+/* Thoroughly test that block is valid. */
 static int sm_check_block(struct sm_ftl *ftl, int zone, int block)
 {
        int boffset;
@@ -526,7 +526,7 @@ static int sm_check_block(struct sm_ftl *ftl, int zone, int block)
        for (boffset = 0; boffset < ftl->block_size;
                                        boffset += SM_SECTOR_SIZE) {
 
-               /* This shoudn't happen anyway */
+               /* This shouldn't happen anyway */
                if (sm_read_sector(ftl, zone, block, boffset, NULL, &oob))
                        return -2;
 
index 5cd18979333296b738696d9430d79b2cd4ce2775..976e3d28b962de39870e70be8bfd3d3c29c70bff 100644 (file)
@@ -135,8 +135,7 @@ static int get_valid_cis_sector(struct mtd_info *mtd)
                                /* Found */
                                cis_sector = (int)(offset >> SECTOR_SHIFT);
                        } else {
-                               DEBUG(MTD_DEBUG_LEVEL1,
-                                       "SSFDC_RO: CIS/IDI sector not found"
+                               pr_debug("SSFDC_RO: CIS/IDI sector not found"
                                        " on %s (mtd%d)\n", mtd->name,
                                        mtd->index);
                        }
@@ -170,7 +169,7 @@ static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf)
        struct mtd_oob_ops ops;
        int ret;
 
-       ops.mode = MTD_OOB_RAW;
+       ops.mode = MTD_OPS_RAW;
        ops.ooboffs = 0;
        ops.ooblen = OOB_SIZE;
        ops.oobbuf = buf;
@@ -221,8 +220,7 @@ static int get_logical_address(uint8_t *oob_buf)
                        block_address >>= 1;
 
                        if (get_parity(block_address, 10) != parity) {
-                               DEBUG(MTD_DEBUG_LEVEL0,
-                                       "SSFDC_RO: logical address field%d"
+                               pr_debug("SSFDC_RO: logical address field%d"
                                        "parity error(0x%04X)\n", j+1,
                                        block_address);
                        } else {
@@ -235,7 +233,7 @@ static int get_logical_address(uint8_t *oob_buf)
        if (!ok)
                block_address = -2;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "SSFDC_RO: get_logical_address() %d\n",
+       pr_debug("SSFDC_RO: get_logical_address() %d\n",
                block_address);
 
        return block_address;
@@ -249,7 +247,7 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc)
        int ret, block_address, phys_block;
        struct mtd_info *mtd = ssfdc->mbd.mtd;
 
-       DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: build_block_map() nblks=%d (%luK)\n",
+       pr_debug("SSFDC_RO: build_block_map() nblks=%d (%luK)\n",
              ssfdc->map_len,
              (unsigned long)ssfdc->map_len * ssfdc->erase_size / 1024);
 
@@ -262,8 +260,7 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc)
 
                ret = read_raw_oob(mtd, offset, oob_buf);
                if (ret < 0) {
-                       DEBUG(MTD_DEBUG_LEVEL0,
-                               "SSFDC_RO: mtd read_oob() failed at %lu\n",
+                       pr_debug("SSFDC_RO: mtd read_oob() failed at %lu\n",
                                offset);
                        return -1;
                }
@@ -279,8 +276,7 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc)
                        ssfdc->logic_block_map[block_address] =
                                (unsigned short)phys_block;
 
-                       DEBUG(MTD_DEBUG_LEVEL2,
-                               "SSFDC_RO: build_block_map() phys_block=%d,"
+                       pr_debug("SSFDC_RO: build_block_map() phys_block=%d,"
                                "logic_block_addr=%d, zone=%d\n",
                                phys_block, block_address, zone_index);
                }
@@ -304,11 +300,8 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
                return;
 
        ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL);
-       if (!ssfdc) {
-               printk(KERN_WARNING
-                       "SSFDC_RO: out of memory for data structures\n");
+       if (!ssfdc)
                return;
-       }
 
        ssfdc->mbd.mtd = mtd;
        ssfdc->mbd.devnum = -1;
@@ -319,8 +312,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        ssfdc->erase_size = mtd->erasesize;
        ssfdc->map_len = (u32)mtd->size / mtd->erasesize;
 
-       DEBUG(MTD_DEBUG_LEVEL1,
-               "SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n",
+       pr_debug("SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n",
                ssfdc->cis_block, ssfdc->erase_size, ssfdc->map_len,
                DIV_ROUND_UP(ssfdc->map_len, MAX_PHYS_BLK_PER_ZONE));
 
@@ -331,7 +323,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        ssfdc->cylinders = (unsigned short)(((u32)mtd->size >> SECTOR_SHIFT) /
                        ((long)ssfdc->sectors * (long)ssfdc->heads));
 
-       DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n",
+       pr_debug("SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n",
                ssfdc->cylinders, ssfdc->heads , ssfdc->sectors,
                (long)ssfdc->cylinders * (long)ssfdc->heads *
                (long)ssfdc->sectors);
@@ -342,11 +334,8 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        /* Allocate logical block map */
        ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) *
                                         ssfdc->map_len, GFP_KERNEL);
-       if (!ssfdc->logic_block_map) {
-               printk(KERN_WARNING
-                       "SSFDC_RO: out of memory for data structures\n");
+       if (!ssfdc->logic_block_map)
                goto out_err;
-       }
        memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) *
                ssfdc->map_len);
 
@@ -371,7 +360,7 @@ static void ssfdcr_remove_dev(struct mtd_blktrans_dev *dev)
 {
        struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev;
 
-       DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: remove_dev (i=%d)\n", dev->devnum);
+       pr_debug("SSFDC_RO: remove_dev (i=%d)\n", dev->devnum);
 
        del_mtd_blktrans_dev(dev);
        kfree(ssfdc->logic_block_map);
@@ -387,8 +376,7 @@ static int ssfdcr_readsect(struct mtd_blktrans_dev *dev,
        offset = (int)(logic_sect_no % sectors_per_block);
        block_address = (int)(logic_sect_no / sectors_per_block);
 
-       DEBUG(MTD_DEBUG_LEVEL3,
-               "SSFDC_RO: ssfdcr_readsect(%lu) sec_per_blk=%d, ofst=%d,"
+       pr_debug("SSFDC_RO: ssfdcr_readsect(%lu) sec_per_blk=%d, ofst=%d,"
                " block_addr=%d\n", logic_sect_no, sectors_per_block, offset,
                block_address);
 
@@ -397,8 +385,7 @@ static int ssfdcr_readsect(struct mtd_blktrans_dev *dev,
 
        block_address = ssfdc->logic_block_map[block_address];
 
-       DEBUG(MTD_DEBUG_LEVEL3,
-               "SSFDC_RO: ssfdcr_readsect() phys_block_addr=%d\n",
+       pr_debug("SSFDC_RO: ssfdcr_readsect() phys_block_addr=%d\n",
                block_address);
 
        if (block_address < 0xffff) {
@@ -407,8 +394,7 @@ static int ssfdcr_readsect(struct mtd_blktrans_dev *dev,
                sect_no = (unsigned long)block_address * sectors_per_block +
                                offset;
 
-               DEBUG(MTD_DEBUG_LEVEL3,
-                       "SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n",
+               pr_debug("SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n",
                        sect_no);
 
                if (read_physical_sector(ssfdc->mbd.mtd, buf, sect_no) < 0)
@@ -424,7 +410,7 @@ static int ssfdcr_getgeo(struct mtd_blktrans_dev *dev,  struct hd_geometry *geo)
 {
        struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev;
 
-       DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: ssfdcr_getgeo() C=%d, H=%d, S=%d\n",
+       pr_debug("SSFDC_RO: ssfdcr_getgeo() C=%d, H=%d, S=%d\n",
                        ssfdc->cylinders, ssfdc->heads, ssfdc->sectors);
 
        geo->heads = ssfdc->heads;
index dec92ae6111a190b0ad8493ad5098c996a7a0616..933f7e5f32d301a90f7256750b03c8a1542a9609 100644 (file)
@@ -30,7 +30,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_oobtest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -131,7 +131,7 @@ static int write_eraseblock(int ebnum)
 
        for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
                set_random_data(writebuf, use_len);
-               ops.mode      = MTD_OOB_AUTO;
+               ops.mode      = MTD_OPS_AUTO_OOB;
                ops.len       = 0;
                ops.retlen    = 0;
                ops.ooblen    = use_len;
@@ -184,7 +184,7 @@ static int verify_eraseblock(int ebnum)
 
        for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
                set_random_data(writebuf, use_len);
-               ops.mode      = MTD_OOB_AUTO;
+               ops.mode      = MTD_OPS_AUTO_OOB;
                ops.len       = 0;
                ops.retlen    = 0;
                ops.ooblen    = use_len;
@@ -211,7 +211,7 @@ static int verify_eraseblock(int ebnum)
                if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
                        int k;
 
-                       ops.mode      = MTD_OOB_AUTO;
+                       ops.mode      = MTD_OPS_AUTO_OOB;
                        ops.len       = 0;
                        ops.retlen    = 0;
                        ops.ooblen    = mtd->ecclayout->oobavail;
@@ -276,7 +276,7 @@ static int verify_eraseblock_in_one_go(int ebnum)
        size_t len = mtd->ecclayout->oobavail * pgcnt;
 
        set_random_data(writebuf, len);
-       ops.mode      = MTD_OOB_AUTO;
+       ops.mode      = MTD_OPS_AUTO_OOB;
        ops.len       = 0;
        ops.retlen    = 0;
        ops.ooblen    = len;
@@ -366,6 +366,13 @@ static int __init mtd_oobtest_init(void)
 
        printk(KERN_INFO "\n");
        printk(KERN_INFO "=================================================\n");
+
+       if (dev < 0) {
+               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               return -EINVAL;
+       }
+
        printk(PRINT_PREF "MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
@@ -507,7 +514,7 @@ static int __init mtd_oobtest_init(void)
                addr0 += mtd->erasesize;
 
        /* Attempt to write off end of OOB */
-       ops.mode      = MTD_OOB_AUTO;
+       ops.mode      = MTD_OPS_AUTO_OOB;
        ops.len       = 0;
        ops.retlen    = 0;
        ops.ooblen    = 1;
@@ -527,7 +534,7 @@ static int __init mtd_oobtest_init(void)
        }
 
        /* Attempt to read off end of OOB */
-       ops.mode      = MTD_OOB_AUTO;
+       ops.mode      = MTD_OPS_AUTO_OOB;
        ops.len       = 0;
        ops.retlen    = 0;
        ops.ooblen    = 1;
@@ -551,7 +558,7 @@ static int __init mtd_oobtest_init(void)
                       "block is bad\n");
        else {
                /* Attempt to write off end of device */
-               ops.mode      = MTD_OOB_AUTO;
+               ops.mode      = MTD_OPS_AUTO_OOB;
                ops.len       = 0;
                ops.retlen    = 0;
                ops.ooblen    = mtd->ecclayout->oobavail + 1;
@@ -571,7 +578,7 @@ static int __init mtd_oobtest_init(void)
                }
 
                /* Attempt to read off end of device */
-               ops.mode      = MTD_OOB_AUTO;
+               ops.mode      = MTD_OPS_AUTO_OOB;
                ops.len       = 0;
                ops.retlen    = 0;
                ops.ooblen    = mtd->ecclayout->oobavail + 1;
@@ -595,7 +602,7 @@ static int __init mtd_oobtest_init(void)
                        goto out;
 
                /* Attempt to write off end of device */
-               ops.mode      = MTD_OOB_AUTO;
+               ops.mode      = MTD_OPS_AUTO_OOB;
                ops.len       = 0;
                ops.retlen    = 0;
                ops.ooblen    = mtd->ecclayout->oobavail;
@@ -615,7 +622,7 @@ static int __init mtd_oobtest_init(void)
                }
 
                /* Attempt to read off end of device */
-               ops.mode      = MTD_OOB_AUTO;
+               ops.mode      = MTD_OPS_AUTO_OOB;
                ops.len       = 0;
                ops.retlen    = 0;
                ops.ooblen    = mtd->ecclayout->oobavail;
@@ -655,7 +662,7 @@ static int __init mtd_oobtest_init(void)
                addr = (i + 1) * mtd->erasesize - mtd->writesize;
                for (pg = 0; pg < cnt; ++pg) {
                        set_random_data(writebuf, sz);
-                       ops.mode      = MTD_OOB_AUTO;
+                       ops.mode      = MTD_OPS_AUTO_OOB;
                        ops.len       = 0;
                        ops.retlen    = 0;
                        ops.ooblen    = sz;
@@ -683,7 +690,7 @@ static int __init mtd_oobtest_init(void)
                        continue;
                set_random_data(writebuf, mtd->ecclayout->oobavail * 2);
                addr = (i + 1) * mtd->erasesize - mtd->writesize;
-               ops.mode      = MTD_OOB_AUTO;
+               ops.mode      = MTD_OPS_AUTO_OOB;
                ops.len       = 0;
                ops.retlen    = 0;
                ops.ooblen    = mtd->ecclayout->oobavail * 2;
index 00b937e38c1d509abcda5cbd6cfc429c06b0807b..afafb6935fd0870707d13f9b7ea12cfbbb69af56 100644 (file)
@@ -30,7 +30,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_pagetest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -128,7 +128,7 @@ static int verify_eraseblock(int ebnum)
        for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
                /* Do a read to set the internal dataRAMs to different data */
                err = mtd->read(mtd, addr0, bufsize, &read, twopages);
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -136,7 +136,7 @@ static int verify_eraseblock(int ebnum)
                        return err;
                }
                err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages);
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -146,7 +146,7 @@ static int verify_eraseblock(int ebnum)
                memset(twopages, 0, bufsize);
                read = 0;
                err = mtd->read(mtd, addr, bufsize, &read, twopages);
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -164,7 +164,7 @@ static int verify_eraseblock(int ebnum)
                unsigned long oldnext = next;
                /* Do a read to set the internal dataRAMs to different data */
                err = mtd->read(mtd, addr0, bufsize, &read, twopages);
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -172,7 +172,7 @@ static int verify_eraseblock(int ebnum)
                        return err;
                }
                err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages);
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -182,7 +182,7 @@ static int verify_eraseblock(int ebnum)
                memset(twopages, 0, bufsize);
                read = 0;
                err = mtd->read(mtd, addr, bufsize, &read, twopages);
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != bufsize) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -231,7 +231,7 @@ static int crosstest(void)
        read = 0;
        addr = addrn - pgsize - pgsize;
        err = mtd->read(mtd, addr, pgsize, &read, pp1);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
                printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -244,7 +244,7 @@ static int crosstest(void)
        read = 0;
        addr = addrn - pgsize - pgsize - pgsize;
        err = mtd->read(mtd, addr, pgsize, &read, pp1);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
                printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -258,7 +258,7 @@ static int crosstest(void)
        addr = addr0;
        printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
        err = mtd->read(mtd, addr, pgsize, &read, pp2);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
                printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -272,7 +272,7 @@ static int crosstest(void)
        addr = addrn - pgsize;
        printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
        err = mtd->read(mtd, addr, pgsize, &read, pp3);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
                printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -286,7 +286,7 @@ static int crosstest(void)
        addr = addr0;
        printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
        err = mtd->read(mtd, addr, pgsize, &read, pp4);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
                printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -345,7 +345,7 @@ static int erasecrosstest(void)
        printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
        memset(readbuf, 0, pgsize);
        err = mtd->read(mtd, addr0, pgsize, &read, readbuf);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
                printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -383,7 +383,7 @@ static int erasecrosstest(void)
        printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
        memset(readbuf, 0, pgsize);
        err = mtd->read(mtd, addr0, pgsize, &read, readbuf);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
                printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -439,7 +439,7 @@ static int erasetest(void)
 
        printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
        err = mtd->read(mtd, addr0, pgsize, &read, twopages);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != pgsize) {
                printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -504,6 +504,13 @@ static int __init mtd_pagetest_init(void)
 
        printk(KERN_INFO "\n");
        printk(KERN_INFO "=================================================\n");
+
+       if (dev < 0) {
+               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               return -EINVAL;
+       }
+
        printk(PRINT_PREF "MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
index afe71aa15c4b4493c5e2c5d50946d71122c35b98..550fe51225a731bcc434ac04ef8890588521b0a6 100644 (file)
@@ -29,7 +29,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_readtest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -66,7 +66,7 @@ static int read_eraseblock_by_page(int ebnum)
                if (mtd->oobsize) {
                        struct mtd_oob_ops ops;
 
-                       ops.mode      = MTD_OOB_PLACE;
+                       ops.mode      = MTD_OPS_PLACE_OOB;
                        ops.len       = 0;
                        ops.retlen    = 0;
                        ops.ooblen    = mtd->oobsize;
@@ -75,7 +75,8 @@ static int read_eraseblock_by_page(int ebnum)
                        ops.datbuf    = NULL;
                        ops.oobbuf    = oobbuf;
                        ret = mtd->read_oob(mtd, addr, &ops);
-                       if (ret || ops.oobretlen != mtd->oobsize) {
+                       if ((ret && !mtd_is_bitflip(ret)) ||
+                                       ops.oobretlen != mtd->oobsize) {
                                printk(PRINT_PREF "error: read oob failed at "
                                                  "%#llx\n", (long long)addr);
                                if (!err)
@@ -169,6 +170,12 @@ static int __init mtd_readtest_init(void)
 
        printk(KERN_INFO "\n");
        printk(KERN_INFO "=================================================\n");
+
+       if (dev < 0) {
+               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+               return -EINVAL;
+       }
+
        printk(PRINT_PREF "MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
index 627d4e2466a3bccbedd3ca27c304f2b47bd414ca..493b367bdd35211af2db7273d981398a938dd039 100644 (file)
@@ -29,7 +29,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_speedtest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -216,7 +216,7 @@ static int read_eraseblock(int ebnum)
 
        err = mtd->read(mtd, addr, mtd->erasesize, &read, iobuf);
        /* Ignore corrected ECC errors */
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (err || read != mtd->erasesize) {
                printk(PRINT_PREF "error: read failed at %#llx\n", addr);
@@ -237,7 +237,7 @@ static int read_eraseblock_by_page(int ebnum)
        for (i = 0; i < pgcnt; i++) {
                err = mtd->read(mtd, addr, pgsize, &read, buf);
                /* Ignore corrected ECC errors */
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != pgsize) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -263,7 +263,7 @@ static int read_eraseblock_by_2pages(int ebnum)
        for (i = 0; i < n; i++) {
                err = mtd->read(mtd, addr, sz, &read, buf);
                /* Ignore corrected ECC errors */
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != sz) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -278,7 +278,7 @@ static int read_eraseblock_by_2pages(int ebnum)
        if (pgcnt % 2) {
                err = mtd->read(mtd, addr, pgsize, &read, buf);
                /* Ignore corrected ECC errors */
-               if (err == -EUCLEAN)
+               if (mtd_is_bitflip(err))
                        err = 0;
                if (err || read != pgsize) {
                        printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -361,6 +361,13 @@ static int __init mtd_speedtest_init(void)
 
        printk(KERN_INFO "\n");
        printk(KERN_INFO "=================================================\n");
+
+       if (dev < 0) {
+               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               return -EINVAL;
+       }
+
        if (count)
                printk(PRINT_PREF "MTD device: %d    count: %d\n", dev, count);
        else
index 531625fc9259cdd167f0ade4755cf1f71cdefaa2..52ffd9120e0ded0eaf45d262cb4b6f115aad0ada 100644 (file)
@@ -30,7 +30,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_stresstest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -154,7 +154,7 @@ static int do_read(void)
        }
        addr = eb * mtd->erasesize + offs;
        err = mtd->read(mtd, addr, len, &read, readbuf);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                err = 0;
        if (unlikely(err || read != len)) {
                printk(PRINT_PREF "error: read failed at 0x%llx\n",
@@ -250,6 +250,13 @@ static int __init mtd_stresstest_init(void)
 
        printk(KERN_INFO "\n");
        printk(KERN_INFO "=================================================\n");
+
+       if (dev < 0) {
+               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               return -EINVAL;
+       }
+
        printk(PRINT_PREF "MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
index 334eae53a3dba64a50ce117d83883434fa53cd91..1a05bfac4eeee5f6f9406b469ab27a74760c3cc8 100644 (file)
@@ -29,7 +29,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_subpagetest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -198,7 +198,7 @@ static int verify_eraseblock(int ebnum)
        read = 0;
        err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
        if (unlikely(err || read != subpgsize)) {
-               if (err == -EUCLEAN && read == subpgsize) {
+               if (mtd_is_bitflip(err) && read == subpgsize) {
                        printk(PRINT_PREF "ECC correction at %#llx\n",
                               (long long)addr);
                        err = 0;
@@ -226,7 +226,7 @@ static int verify_eraseblock(int ebnum)
        read = 0;
        err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
        if (unlikely(err || read != subpgsize)) {
-               if (err == -EUCLEAN && read == subpgsize) {
+               if (mtd_is_bitflip(err) && read == subpgsize) {
                        printk(PRINT_PREF "ECC correction at %#llx\n",
                               (long long)addr);
                        err = 0;
@@ -264,7 +264,7 @@ static int verify_eraseblock2(int ebnum)
                read = 0;
                err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf);
                if (unlikely(err || read != subpgsize * k)) {
-                       if (err == -EUCLEAN && read == subpgsize * k) {
+                       if (mtd_is_bitflip(err) && read == subpgsize * k) {
                                printk(PRINT_PREF "ECC correction at %#llx\n",
                                       (long long)addr);
                                err = 0;
@@ -298,7 +298,7 @@ static int verify_eraseblock_ff(int ebnum)
                read = 0;
                err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
                if (unlikely(err || read != subpgsize)) {
-                       if (err == -EUCLEAN && read == subpgsize) {
+                       if (mtd_is_bitflip(err) && read == subpgsize) {
                                printk(PRINT_PREF "ECC correction at %#llx\n",
                                       (long long)addr);
                                err = 0;
@@ -379,6 +379,13 @@ static int __init mtd_subpagetest_init(void)
 
        printk(KERN_INFO "\n");
        printk(KERN_INFO "=================================================\n");
+
+       if (dev < 0) {
+               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               return -EINVAL;
+       }
+
        printk(PRINT_PREF "MTD device: %d\n", dev);
 
        mtd = get_mtd_device(NULL, dev);
index 5c6c3d2489014960056a5f27916a8c2924810549..03ab649a6964292f50f40f9073c45ae097a47b8e 100644 (file)
@@ -46,7 +46,7 @@ static int pgcnt;
 module_param(pgcnt, int, S_IRUGO);
 MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)");
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -138,7 +138,7 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf)
 
 retry:
        err = mtd->read(mtd, addr, len, &read, check_buf);
-       if (err == -EUCLEAN)
+       if (mtd_is_bitflip(err))
                printk(PRINT_PREF "single bit flip occurred at EB %d "
                       "MTD reported that it was fixed.\n", ebnum);
        else if (err) {
@@ -213,6 +213,13 @@ static int __init tort_init(void)
        printk(KERN_INFO "=================================================\n");
        printk(PRINT_PREF "Warning: this program is trying to wear out your "
               "flash, stop it if this is not wanted.\n");
+
+       if (dev < 0) {
+               printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+               printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+               return -EINVAL;
+       }
+
        printk(PRINT_PREF "MTD device: %d\n", dev);
        printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n",
               ebcnt, eb, eb + ebcnt - 1, dev);
index 4be671815014ee3b054f2ba8f704781dfbc1f032..fb7f19b62d91fabe2fdc785bf08aa1a32f523497 100644 (file)
@@ -443,7 +443,7 @@ retry:
                if (err == UBI_IO_BITFLIPS) {
                        scrub = 1;
                        err = 0;
-               } else if (err == -EBADMSG) {
+               } else if (mtd_is_eccerr(err)) {
                        if (vol->vol_type == UBI_DYNAMIC_VOLUME)
                                goto out_unlock;
                        scrub = 1;
index 6ba55c2358738d3d3645f816b55c0286ee15562b..f20b6f22f240378ce6386ee8c4e59d25f81cb3de 100644 (file)
@@ -172,9 +172,9 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
 retry:
        err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
        if (err) {
-               const char *errstr = (err == -EBADMSG) ? " (ECC error)" : "";
+               const char *errstr = mtd_is_eccerr(err) ? " (ECC error)" : "";
 
-               if (err == -EUCLEAN) {
+               if (mtd_is_bitflip(err)) {
                        /*
                         * -EUCLEAN is reported if there was a bit-flip which
                         * was corrected, so this is harmless.
@@ -205,7 +205,7 @@ retry:
                 * all the requested data. But some buggy drivers might do
                 * this, so we change it to -EIO.
                 */
-               if (read != len && err == -EBADMSG) {
+               if (read != len && mtd_is_eccerr(err)) {
                        ubi_assert(0);
                        err = -EIO;
                }
@@ -469,7 +469,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
 
 out:
        mutex_unlock(&ubi->buf_mutex);
-       if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+       if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) {
                /*
                 * If a bit-flip or data integrity error was detected, the test
                 * has not passed because it happened on a freshly erased
@@ -760,7 +760,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 
        read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
        if (read_err) {
-               if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+               if (read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
                        return read_err;
 
                /*
@@ -776,7 +776,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 
        magic = be32_to_cpu(ec_hdr->magic);
        if (magic != UBI_EC_HDR_MAGIC) {
-               if (read_err == -EBADMSG)
+               if (mtd_is_eccerr(read_err))
                        return UBI_IO_BAD_HDR_EBADMSG;
 
                /*
@@ -1032,12 +1032,12 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
        p = (char *)vid_hdr - ubi->vid_hdr_shift;
        read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
                          ubi->vid_hdr_alsize);
-       if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+       if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
                return read_err;
 
        magic = be32_to_cpu(vid_hdr->magic);
        if (magic != UBI_VID_HDR_MAGIC) {
-               if (read_err == -EBADMSG)
+               if (mtd_is_eccerr(read_err))
                        return UBI_IO_BAD_HDR_EBADMSG;
 
                if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
@@ -1219,7 +1219,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
                return -ENOMEM;
 
        err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
-       if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+       if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
                goto exit;
 
        crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
@@ -1306,7 +1306,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
        p = (char *)vid_hdr - ubi->vid_hdr_shift;
        err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
                          ubi->vid_hdr_alsize);
-       if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+       if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
                goto exit;
 
        crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
@@ -1358,7 +1358,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
        }
 
        err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1);
-       if (err && err != -EUCLEAN)
+       if (err && !mtd_is_bitflip(err))
                goto out_free;
 
        for (i = 0; i < len; i++) {
@@ -1422,7 +1422,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
        }
 
        err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
-       if (err && err != -EUCLEAN) {
+       if (err && !mtd_is_bitflip(err)) {
                ubi_err("error %d while reading %d bytes from PEB %d:%d, "
                        "read %zd bytes", err, len, pnum, offset, read);
                goto error;
index d39716e5b204c8fce14e2383dfdc1d43c91d972d..1a35fc5e3b40a947451acc340b58b7c29f2ded41 100644 (file)
@@ -410,7 +410,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
                return 0;
 
        err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
-       if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) {
+       if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
                ubi_warn("mark volume %d as corrupted", vol_id);
                vol->corrupted = 1;
        }
index ff2a65c37f69a6c12e7dbbdafb0c8367e951ce49..f6a7d7ac4b98a6fb1f2dd3b8d2f0abad4b06bd45 100644 (file)
@@ -81,7 +81,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
 
                err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1);
                if (err) {
-                       if (err == -EBADMSG)
+                       if (mtd_is_eccerr(err))
                                err = 1;
                        break;
                }
index a3a198f9b98dd05ea7690f4239c6874a9a3f0526..0cb17d936b5a46581ab6360c1b8307211b3c01c0 100644 (file)
@@ -395,7 +395,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
        }
 
        err = ubi_io_read_data(ubi, buf, pnum, 0, len);
-       if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+       if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
                goto out_free_buf;
 
        data_crc = be32_to_cpu(vid_hdr->data_crc);
@@ -793,7 +793,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
 
        err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
                          ubi->leb_size);
-       if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+       if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) {
                /*
                 * Bit-flips or integrity errors while reading the data area.
                 * It is difficult to say for sure what type of corruption is
index 4b50a3029b8467817c582eb6488007cfa3fdfd46..9ad18da1891de31d2e792de57ede91626764e431 100644 (file)
@@ -423,7 +423,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
 
                err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
                                       ubi->vtbl_size);
-               if (err == UBI_IO_BITFLIPS || err == -EBADMSG)
+               if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err))
                        /*
                         * Scrub the PEB later. Note, -EBADMSG indicates an
                         * uncorrectable ECC error, but we have our own CRC and
index 583f66cd5bbd63dc199468b87b96baf32582bcb1..654a5e94e0e7c4f227c93b75a7791c406c586d38 100644 (file)
@@ -245,6 +245,8 @@ source "drivers/net/ethernet/Kconfig"
 
 source "drivers/net/fddi/Kconfig"
 
+source "drivers/net/hippi/Kconfig"
+
 config NET_SB1000
        tristate "General Instruments Surfboard 1000"
        depends on PNP
index b2b9109b6712ef63212600811d3b879687dbc215..b0c577256487b4b7c35d690da3a2ca619d2deb4c 100644 (file)
@@ -560,8 +560,8 @@ static int bond_update_speed_duplex(struct slave *slave)
        u32 slave_speed;
        int res;
 
-       slave->speed = -1;
-       slave->duplex = -1;
+       slave->speed = SPEED_UNKNOWN;
+       slave->duplex = DUPLEX_UNKNOWN;
 
        res = __ethtool_get_settings(slave_dev, &ecmd);
        if (res < 0)
index 2acf0b080169203fcaa6d29c92e4081607a57ef3..ad284baafe87df64599c3335106a31aa0d6b3ec0 100644 (file)
@@ -158,12 +158,12 @@ static void bond_info_show_slave(struct seq_file *seq,
        seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
        seq_printf(seq, "MII Status: %s\n",
                   (slave->link == BOND_LINK_UP) ?  "up" : "down");
-       if (slave->speed == -1)
+       if (slave->speed == SPEED_UNKNOWN)
                seq_printf(seq, "Speed: %s\n", "Unknown");
        else
                seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
 
-       if (slave->duplex == -1)
+       if (slave->duplex == DUPLEX_UNKNOWN)
                seq_printf(seq, "Duplex: %s\n", "Unknown");
        else
                seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
index 5a20804fdece8d1c281e310e49509973185a33ed..4ef7e2fd9fe6f5b577c13fc56a5b2ae45a54a0bd 100644 (file)
@@ -319,6 +319,13 @@ static ssize_t bonding_store_mode(struct device *d,
                goto out;
        }
 
+       if (bond->slave_cnt > 0) {
+               pr_err("unable to update mode of %s because it has slaves.\n",
+                       bond->dev->name);
+               ret = -EPERM;
+               goto out;
+       }
+
        new_value = bond_parse_parm(buf, bond_mode_tbl);
        if (new_value < 0)  {
                pr_err("%s: Ignoring invalid mode value %.*s.\n",
index be5dde040261b748e75535e4521cc5974f946b75..94b7f287d6c52a1a0031e32726478759800a10d5 100644 (file)
@@ -10,7 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
 obj-$(CONFIG_NET_VENDOR_AMD) += amd/
 obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
 obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
-obj-$(CONFIG_NET_ATMEL) += cadence/
+obj-$(CONFIG_NET_CADENCE) += cadence/
 obj-$(CONFIG_NET_BFIN) += adi/
 obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/
 obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/
index 6486ab8c8fc87d803a6e5a3d507d50796704db08..2f6361e949f0c836562ff896928cb6709abf883a 100644 (file)
@@ -10548,33 +10548,38 @@ do {                                                                  \
 
 int bnx2x_init_firmware(struct bnx2x *bp)
 {
-       const char *fw_file_name;
        struct bnx2x_fw_file_hdr *fw_hdr;
        int rc;
 
-       if (CHIP_IS_E1(bp))
-               fw_file_name = FW_FILE_NAME_E1;
-       else if (CHIP_IS_E1H(bp))
-               fw_file_name = FW_FILE_NAME_E1H;
-       else if (!CHIP_IS_E1x(bp))
-               fw_file_name = FW_FILE_NAME_E2;
-       else {
-               BNX2X_ERR("Unsupported chip revision\n");
-               return -EINVAL;
-       }
 
-       BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
+       if (!bp->firmware) {
+               const char *fw_file_name;
 
-       rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
-       if (rc) {
-               BNX2X_ERR("Can't load firmware file %s\n", fw_file_name);
-               goto request_firmware_exit;
-       }
+               if (CHIP_IS_E1(bp))
+                       fw_file_name = FW_FILE_NAME_E1;
+               else if (CHIP_IS_E1H(bp))
+                       fw_file_name = FW_FILE_NAME_E1H;
+               else if (!CHIP_IS_E1x(bp))
+                       fw_file_name = FW_FILE_NAME_E2;
+               else {
+                       BNX2X_ERR("Unsupported chip revision\n");
+                       return -EINVAL;
+               }
+               BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
 
-       rc = bnx2x_check_firmware(bp);
-       if (rc) {
-               BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
-               goto request_firmware_exit;
+               rc = request_firmware(&bp->firmware, fw_file_name,
+                                     &bp->pdev->dev);
+               if (rc) {
+                       BNX2X_ERR("Can't load firmware file %s\n",
+                                 fw_file_name);
+                       goto request_firmware_exit;
+               }
+
+               rc = bnx2x_check_firmware(bp);
+               if (rc) {
+                       BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
+                       goto request_firmware_exit;
+               }
        }
 
        fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data;
@@ -10630,6 +10635,7 @@ static void bnx2x_release_firmware(struct bnx2x *bp)
        kfree(bp->init_ops);
        kfree(bp->init_data);
        release_firmware(bp->firmware);
+       bp->firmware = NULL;
 }
 
 
@@ -10925,6 +10931,8 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
        if (bp->doorbells)
                iounmap(bp->doorbells);
 
+       bnx2x_release_firmware(bp);
+
        bnx2x_free_mem_bp(bp);
 
        free_netdev(dev);
index 0440425c83d6820e3ba2ad12ec57430ec9896492..14517691f8dbe9a759abe26a7e5f5debd2515eb4 100644 (file)
@@ -5380,7 +5380,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp,
        rc = drv->init_fw(bp);
        if (rc) {
                BNX2X_ERR("Error loading firmware\n");
-               goto fw_init_err;
+               goto init_err;
        }
 
        /* Handle the beginning of COMMON_XXX pases separatelly... */
@@ -5388,25 +5388,25 @@ static int bnx2x_func_hw_init(struct bnx2x *bp,
        case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
                rc = bnx2x_func_init_cmn_chip(bp, drv);
                if (rc)
-                       goto init_hw_err;
+                       goto init_err;
 
                break;
        case FW_MSG_CODE_DRV_LOAD_COMMON:
                rc = bnx2x_func_init_cmn(bp, drv);
                if (rc)
-                       goto init_hw_err;
+                       goto init_err;
 
                break;
        case FW_MSG_CODE_DRV_LOAD_PORT:
                rc = bnx2x_func_init_port(bp, drv);
                if (rc)
-                       goto init_hw_err;
+                       goto init_err;
 
                break;
        case FW_MSG_CODE_DRV_LOAD_FUNCTION:
                rc = bnx2x_func_init_func(bp, drv);
                if (rc)
-                       goto init_hw_err;
+                       goto init_err;
 
                break;
        default:
@@ -5414,10 +5414,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp,
                rc = -EINVAL;
        }
 
-init_hw_err:
-       drv->release_fw(bp);
-
-fw_init_err:
+init_err:
        drv->gunzip_end(bp);
 
        /* In case of success, complete the comand immediatelly: no ramrods
index 161cbbb4814ad1ae99fa75f3473a28fac8bcf768..bf4074167d6a321e8f5888c2e2909b0b71e1f62b 100644 (file)
@@ -89,10 +89,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME                "tg3"
 #define TG3_MAJ_NUM                    3
-#define TG3_MIN_NUM                    120
+#define TG3_MIN_NUM                    121
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "August 18, 2011"
+#define DRV_MODULE_RELDATE     "November 2, 2011"
 
 #define RESET_KIND_SHUTDOWN    0
 #define RESET_KIND_INIT                1
@@ -628,19 +628,23 @@ static void tg3_ape_lock_init(struct tg3 *tp)
                regbase = TG3_APE_PER_LOCK_GRANT;
 
        /* Make sure the driver hasn't any stale locks. */
-       for (i = 0; i < 8; i++) {
-               if (i == TG3_APE_LOCK_GPIO)
-                       continue;
-               tg3_ape_write32(tp, regbase + 4 * i, APE_LOCK_GRANT_DRIVER);
+       for (i = TG3_APE_LOCK_PHY0; i <= TG3_APE_LOCK_GPIO; i++) {
+               switch (i) {
+               case TG3_APE_LOCK_PHY0:
+               case TG3_APE_LOCK_PHY1:
+               case TG3_APE_LOCK_PHY2:
+               case TG3_APE_LOCK_PHY3:
+                       bit = APE_LOCK_GRANT_DRIVER;
+                       break;
+               default:
+                       if (!tp->pci_fn)
+                               bit = APE_LOCK_GRANT_DRIVER;
+                       else
+                               bit = 1 << tp->pci_fn;
+               }
+               tg3_ape_write32(tp, regbase + 4 * i, bit);
        }
 
-       /* Clear the correct bit of the GPIO lock too. */
-       if (!tp->pci_fn)
-               bit = APE_LOCK_GRANT_DRIVER;
-       else
-               bit = 1 << tp->pci_fn;
-
-       tg3_ape_write32(tp, regbase + 4 * TG3_APE_LOCK_GPIO, bit);
 }
 
 static int tg3_ape_lock(struct tg3 *tp, int locknum)
@@ -658,6 +662,10 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
                        return 0;
        case TG3_APE_LOCK_GRC:
        case TG3_APE_LOCK_MEM:
+               if (!tp->pci_fn)
+                       bit = APE_LOCK_REQ_DRIVER;
+               else
+                       bit = 1 << tp->pci_fn;
                break;
        default:
                return -EINVAL;
@@ -673,11 +681,6 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
 
        off = 4 * locknum;
 
-       if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn)
-               bit = APE_LOCK_REQ_DRIVER;
-       else
-               bit = 1 << tp->pci_fn;
-
        tg3_ape_write32(tp, req + off, bit);
 
        /* Wait for up to 1 millisecond to acquire lock. */
@@ -710,6 +713,10 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
                        return;
        case TG3_APE_LOCK_GRC:
        case TG3_APE_LOCK_MEM:
+               if (!tp->pci_fn)
+                       bit = APE_LOCK_GRANT_DRIVER;
+               else
+                       bit = 1 << tp->pci_fn;
                break;
        default:
                return;
@@ -720,11 +727,6 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
        else
                gnt = TG3_APE_PER_LOCK_GRANT;
 
-       if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn)
-               bit = APE_LOCK_GRANT_DRIVER;
-       else
-               bit = 1 << tp->pci_fn;
-
        tg3_ape_write32(tp, gnt + 4 * locknum, bit);
 }
 
@@ -5927,6 +5929,18 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
        return work_done;
 }
 
+static inline void tg3_reset_task_schedule(struct tg3 *tp)
+{
+       if (!test_and_set_bit(TG3_FLAG_RESET_TASK_PENDING, tp->tg3_flags))
+               schedule_work(&tp->reset_task);
+}
+
+static inline void tg3_reset_task_cancel(struct tg3 *tp)
+{
+       cancel_work_sync(&tp->reset_task);
+       tg3_flag_clear(tp, RESET_TASK_PENDING);
+}
+
 static int tg3_poll_msix(struct napi_struct *napi, int budget)
 {
        struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi);
@@ -5967,7 +5981,7 @@ static int tg3_poll_msix(struct napi_struct *napi, int budget)
 tx_recovery:
        /* work_done is guaranteed to be less than budget. */
        napi_complete(napi);
-       schedule_work(&tp->reset_task);
+       tg3_reset_task_schedule(tp);
        return work_done;
 }
 
@@ -6002,7 +6016,7 @@ static void tg3_process_error(struct tg3 *tp)
        tg3_dump_state(tp);
 
        tg3_flag_set(tp, ERROR_PROCESSED);
-       schedule_work(&tp->reset_task);
+       tg3_reset_task_schedule(tp);
 }
 
 static int tg3_poll(struct napi_struct *napi, int budget)
@@ -6049,7 +6063,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
 tx_recovery:
        /* work_done is guaranteed to be less than budget. */
        napi_complete(napi);
-       schedule_work(&tp->reset_task);
+       tg3_reset_task_schedule(tp);
        return work_done;
 }
 
@@ -6338,11 +6352,11 @@ static void tg3_reset_task(struct work_struct *work)
 {
        struct tg3 *tp = container_of(work, struct tg3, reset_task);
        int err;
-       unsigned int restart_timer;
 
        tg3_full_lock(tp, 0);
 
        if (!netif_running(tp->dev)) {
+               tg3_flag_clear(tp, RESET_TASK_PENDING);
                tg3_full_unlock(tp);
                return;
        }
@@ -6355,9 +6369,6 @@ static void tg3_reset_task(struct work_struct *work)
 
        tg3_full_lock(tp, 1);
 
-       restart_timer = tg3_flag(tp, RESTART_TIMER);
-       tg3_flag_clear(tp, RESTART_TIMER);
-
        if (tg3_flag(tp, TX_RECOVERY_PENDING)) {
                tp->write32_tx_mbox = tg3_write32_tx_mbox;
                tp->write32_rx_mbox = tg3_write_flush_reg32;
@@ -6372,14 +6383,13 @@ static void tg3_reset_task(struct work_struct *work)
 
        tg3_netif_start(tp);
 
-       if (restart_timer)
-               mod_timer(&tp->timer, jiffies + 1);
-
 out:
        tg3_full_unlock(tp);
 
        if (!err)
                tg3_phy_start(tp);
+
+       tg3_flag_clear(tp, RESET_TASK_PENDING);
 }
 
 static void tg3_tx_timeout(struct net_device *dev)
@@ -6391,7 +6401,7 @@ static void tg3_tx_timeout(struct net_device *dev)
                tg3_dump_state(tp);
        }
 
-       schedule_work(&tp->reset_task);
+       tg3_reset_task_schedule(tp);
 }
 
 /* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */
@@ -6442,31 +6452,26 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget,
                hwbug = 1;
 
        if (tg3_flag(tp, 4K_FIFO_LIMIT)) {
+               u32 prvidx = *entry;
                u32 tmp_flag = flags & ~TXD_FLAG_END;
-               while (len > TG3_TX_BD_DMA_MAX) {
+               while (len > TG3_TX_BD_DMA_MAX && *budget) {
                        u32 frag_len = TG3_TX_BD_DMA_MAX;
                        len -= TG3_TX_BD_DMA_MAX;
 
-                       if (len) {
-                               tnapi->tx_buffers[*entry].fragmented = true;
-                               /* Avoid the 8byte DMA problem */
-                               if (len <= 8) {
-                                       len += TG3_TX_BD_DMA_MAX / 2;
-                                       frag_len = TG3_TX_BD_DMA_MAX / 2;
-                               }
-                       } else
-                               tmp_flag = flags;
-
-                       if (*budget) {
-                               tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
-                                             frag_len, tmp_flag, mss, vlan);
-                               (*budget)--;
-                               *entry = NEXT_TX(*entry);
-                       } else {
-                               hwbug = 1;
-                               break;
+                       /* Avoid the 8byte DMA problem */
+                       if (len <= 8) {
+                               len += TG3_TX_BD_DMA_MAX / 2;
+                               frag_len = TG3_TX_BD_DMA_MAX / 2;
                        }
 
+                       tnapi->tx_buffers[*entry].fragmented = true;
+
+                       tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
+                                     frag_len, tmp_flag, mss, vlan);
+                       *budget -= 1;
+                       prvidx = *entry;
+                       *entry = NEXT_TX(*entry);
+
                        map += frag_len;
                }
 
@@ -6474,10 +6479,11 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget,
                        if (*budget) {
                                tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
                                              len, flags, mss, vlan);
-                               (*budget)--;
+                               *budget -= 1;
                                *entry = NEXT_TX(*entry);
                        } else {
                                hwbug = 1;
+                               tnapi->tx_buffers[prvidx].fragmented = false;
                        }
                }
        } else {
@@ -6509,7 +6515,7 @@ static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last)
                txb = &tnapi->tx_buffers[entry];
        }
 
-       for (i = 0; i < last; i++) {
+       for (i = 0; i <= last; i++) {
                const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
                entry = NEXT_TX(entry);
@@ -6559,6 +6565,8 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
                        dev_kfree_skb(new_skb);
                        ret = -1;
                } else {
+                       u32 save_entry = *entry;
+
                        base_flags |= TXD_FLAG_END;
 
                        tnapi->tx_buffers[*entry].skb = new_skb;
@@ -6568,7 +6576,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
                        if (tg3_tx_frag_set(tnapi, entry, budget, new_addr,
                                            new_skb->len, base_flags,
                                            mss, vlan)) {
-                               tg3_tx_skb_unmap(tnapi, *entry, 0);
+                               tg3_tx_skb_unmap(tnapi, save_entry, -1);
                                dev_kfree_skb(new_skb);
                                ret = -1;
                        }
@@ -6758,11 +6766,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping, len, base_flags |
                          ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0),
-                           mss, vlan))
+                           mss, vlan)) {
                would_hit_hwbug = 1;
-
        /* Now loop through additional data fragments, and queue them. */
-       if (skb_shinfo(skb)->nr_frags > 0) {
+       } else if (skb_shinfo(skb)->nr_frags > 0) {
                u32 tmp_mss = mss;
 
                if (!tg3_flag(tp, HW_TSO_1) &&
@@ -6784,11 +6791,14 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        if (dma_mapping_error(&tp->pdev->dev, mapping))
                                goto dma_error;
 
-                       if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping,
+                       if (!budget ||
+                           tg3_tx_frag_set(tnapi, &entry, &budget, mapping,
                                            len, base_flags |
                                            ((i == last) ? TXD_FLAG_END : 0),
-                                           tmp_mss, vlan))
+                                           tmp_mss, vlan)) {
                                would_hit_hwbug = 1;
+                               break;
+                       }
                }
        }
 
@@ -6828,7 +6838,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 
 dma_error:
-       tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i);
+       tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i);
        tnapi->tx_buffers[tnapi->tx_prod].skb = NULL;
 drop:
        dev_kfree_skb(skb);
@@ -7281,7 +7291,8 @@ static void tg3_free_rings(struct tg3 *tp)
                        if (!skb)
                                continue;
 
-                       tg3_tx_skb_unmap(tnapi, i, skb_shinfo(skb)->nr_frags);
+                       tg3_tx_skb_unmap(tnapi, i,
+                                        skb_shinfo(skb)->nr_frags - 1);
 
                        dev_kfree_skb_any(skb);
                }
@@ -9200,7 +9211,7 @@ static void tg3_timer(unsigned long __opaque)
 {
        struct tg3 *tp = (struct tg3 *) __opaque;
 
-       if (tp->irq_sync)
+       if (tp->irq_sync || tg3_flag(tp, RESET_TASK_PENDING))
                goto restart_timer;
 
        spin_lock(&tp->lock);
@@ -9223,10 +9234,9 @@ static void tg3_timer(unsigned long __opaque)
                }
 
                if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
-                       tg3_flag_set(tp, RESTART_TIMER);
                        spin_unlock(&tp->lock);
-                       schedule_work(&tp->reset_task);
-                       return;
+                       tg3_reset_task_schedule(tp);
+                       goto restart_timer;
                }
        }
 
@@ -9674,15 +9684,14 @@ static int tg3_open(struct net_device *dev)
                struct tg3_napi *tnapi = &tp->napi[i];
                err = tg3_request_irq(tp, i);
                if (err) {
-                       for (i--; i >= 0; i--)
+                       for (i--; i >= 0; i--) {
+                               tnapi = &tp->napi[i];
                                free_irq(tnapi->irq_vec, tnapi);
-                       break;
+                       }
+                       goto err_out2;
                }
        }
 
-       if (err)
-               goto err_out2;
-
        tg3_full_lock(tp, 0);
 
        err = tg3_init_hw(tp, 1);
@@ -9783,7 +9792,7 @@ static int tg3_close(struct net_device *dev)
        struct tg3 *tp = netdev_priv(dev);
 
        tg3_napi_disable(tp);
-       cancel_work_sync(&tp->reset_task);
+       tg3_reset_task_cancel(tp);
 
        netif_tx_stop_all_queues(dev);
 
@@ -11520,7 +11529,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback)
                        break;
        }
 
-       tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, 0);
+       tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, -1);
        dev_kfree_skb(skb);
 
        if (tx_idx != tnapi->tx_prod)
@@ -14228,12 +14237,30 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        val = tr32(MEMARB_MODE);
        tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
 
-       if (tg3_flag(tp, PCIX_MODE)) {
-               pci_read_config_dword(tp->pdev,
-                                     tp->pcix_cap + PCI_X_STATUS, &val);
-               tp->pci_fn = val & 0x7;
-       } else {
-               tp->pci_fn = PCI_FUNC(tp->pdev->devfn) & 3;
+       tp->pci_fn = PCI_FUNC(tp->pdev->devfn) & 3;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+           tg3_flag(tp, 5780_CLASS)) {
+               if (tg3_flag(tp, PCIX_MODE)) {
+                       pci_read_config_dword(tp->pdev,
+                                             tp->pcix_cap + PCI_X_STATUS,
+                                             &val);
+                       tp->pci_fn = val & 0x7;
+               }
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+               tg3_read_mem(tp, NIC_SRAM_CPMU_STATUS, &val);
+               if ((val & NIC_SRAM_CPMUSTAT_SIG_MSK) ==
+                   NIC_SRAM_CPMUSTAT_SIG) {
+                       tp->pci_fn = val & TG3_CPMU_STATUS_FMSK_5717;
+                       tp->pci_fn = tp->pci_fn ? 1 : 0;
+               }
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+                  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+               tg3_read_mem(tp, NIC_SRAM_CPMU_STATUS, &val);
+               if ((val & NIC_SRAM_CPMUSTAT_SIG_MSK) ==
+                   NIC_SRAM_CPMUSTAT_SIG) {
+                       tp->pci_fn = (val & TG3_CPMU_STATUS_FMSK_5719) >>
+                                    TG3_CPMU_STATUS_FSHFT_5719;
+               }
        }
 
        /* Get eeprom hw config before calling tg3_set_power_state().
@@ -15665,7 +15692,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
                if (tp->fw)
                        release_firmware(tp->fw);
 
-               cancel_work_sync(&tp->reset_task);
+               tg3_reset_task_cancel(tp);
 
                if (tg3_flag(tp, USE_PHYLIB)) {
                        tg3_phy_fini(tp);
@@ -15699,7 +15726,7 @@ static int tg3_suspend(struct device *device)
        if (!netif_running(dev))
                return 0;
 
-       flush_work_sync(&tp->reset_task);
+       tg3_reset_task_cancel(tp);
        tg3_phy_stop(tp);
        tg3_netif_stop(tp);
 
@@ -15812,12 +15839,10 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
        tg3_netif_stop(tp);
 
        del_timer_sync(&tp->timer);
-       tg3_flag_clear(tp, RESTART_TIMER);
 
        /* Want to make sure that the reset task doesn't run */
-       cancel_work_sync(&tp->reset_task);
+       tg3_reset_task_cancel(tp);
        tg3_flag_clear(tp, TX_RECOVERY_PENDING);
-       tg3_flag_clear(tp, RESTART_TIMER);
 
        netif_device_detach(netdev);
 
index f32f288134c7b4946334ab59099a577b95cadd36..94b4bd049a33a8e29534e423e560faedadd94fc7 100644 (file)
 #define TG3_CPMU_CLCK_ORIDE            0x00003624
 #define  CPMU_CLCK_ORIDE_MAC_ORIDE_EN   0x80000000
 
+#define TG3_CPMU_STATUS                        0x0000362c
+#define  TG3_CPMU_STATUS_FMSK_5717      0x20000000
+#define  TG3_CPMU_STATUS_FMSK_5719      0xc0000000
+#define  TG3_CPMU_STATUS_FSHFT_5719     30
+
 #define TG3_CPMU_CLCK_STAT             0x00003630
 #define  CPMU_CLCK_STAT_MAC_CLCK_MASK   0x001f0000
 #define  CPMU_CLCK_STAT_MAC_CLCK_62_5   0x00000000
 #define  NIC_SRAM_RGMII_EXT_IBND_RX_EN  0x00000008
 #define  NIC_SRAM_RGMII_EXT_IBND_TX_EN  0x00000010
 
+#define NIC_SRAM_CPMU_STATUS           0x00000e00
+#define  NIC_SRAM_CPMUSTAT_SIG         0x0000362c
+#define  NIC_SRAM_CPMUSTAT_SIG_MSK     0x0000ffff
+
 #define NIC_SRAM_RX_MINI_BUFFER_DESC   0x00001000
 
 #define NIC_SRAM_DMA_DESC_POOL_BASE    0x00002000
 #define  APE_PER_LOCK_GRANT_DRIVER      0x00001000
 
 /* APE convenience enumerations. */
-#define TG3_APE_LOCK_GRC                1
-#define TG3_APE_LOCK_MEM                4
-#define TG3_APE_LOCK_GPIO               7
+#define TG3_APE_LOCK_PHY0              0
+#define TG3_APE_LOCK_GRC               1
+#define TG3_APE_LOCK_PHY1              2
+#define TG3_APE_LOCK_PHY2              3
+#define TG3_APE_LOCK_MEM               4
+#define TG3_APE_LOCK_PHY3              5
+#define TG3_APE_LOCK_GPIO              7
 
 #define TG3_EEPROM_SB_F1R2_MBA_OFF     0x10
 
@@ -2866,7 +2879,6 @@ enum TG3_FLAGS {
        TG3_FLAG_JUMBO_CAPABLE,
        TG3_FLAG_CHIP_RESETTING,
        TG3_FLAG_INIT_COMPLETE,
-       TG3_FLAG_RESTART_TIMER,
        TG3_FLAG_TSO_BUG,
        TG3_FLAG_IS_5788,
        TG3_FLAG_MAX_RXPEND_64,
@@ -2909,6 +2921,7 @@ enum TG3_FLAGS {
        TG3_FLAG_APE_HAS_NCSI,
        TG3_FLAG_5717_PLUS,
        TG3_FLAG_4K_FIFO_LIMIT,
+       TG3_FLAG_RESET_TASK_PENDING,
 
        /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */
        TG3_FLAG_NUMBER_OF_FLAGS,       /* Last entry in enum TG3_FLAGS */
index 98849a1fc749995070dadd607175f55ef89d2fa0..db931916da08c8ddfd26b9068a94b7dddd1bfb46 100644 (file)
@@ -5,8 +5,9 @@
 config HAVE_NET_MACB
        bool
 
-config NET_ATMEL
-       bool "Atmel devices"
+config NET_CADENCE
+       bool "Cadence devices"
+       default y
        depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y.
@@ -20,7 +21,7 @@ config NET_ATMEL
          the remaining Atmel network card questions. If you say Y, you will be
          asked for your specific card in the following questions.
 
-if NET_ATMEL
+if NET_CADENCE
 
 config ARM_AT91_ETHER
        tristate "AT91RM9200 Ethernet support"
@@ -32,14 +33,16 @@ config ARM_AT91_ETHER
          ethernet support, then you should always answer Y to this.
 
 config MACB
-       tristate "Atmel MACB support"
+       tristate "Cadence MACB/GEM support"
        depends on HAVE_NET_MACB
        select PHYLIB
        ---help---
-         The Atmel MACB ethernet interface is found on many AT32 and AT91
-         parts. Say Y to include support for the MACB chip.
+         The Cadence MACB ethernet interface is found on many Atmel AT32 and
+         AT91 parts.  This driver also supports the Cadence GEM (Gigabit
+         Ethernet MAC found in some ARM SoC devices).  Note: the Gigabit mode
+         is not yet supported.  Say Y to include support for the MACB/GEM chip.
 
          To compile this driver as a module, choose M here: the module
          will be called macb.
 
-endif # NET_ATMEL
+endif # NET_CADENCE
index 56624d3034871c4988ddd3e4963206133eaab517..dfeb46cb3f74aca61753789a697ae767bd9012b4 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
 #include <linux/ethtool.h>
+#include <linux/platform_data/macb.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/gfp.h>
@@ -984,7 +985,7 @@ static const struct net_device_ops at91ether_netdev_ops = {
 static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address,
                        struct platform_device *pdev, struct clk *ether_clk)
 {
-       struct at91_eth_data *board_data = pdev->dev.platform_data;
+       struct macb_platform_data *board_data = pdev->dev.platform_data;
        struct net_device *dev;
        struct at91_private *lp;
        unsigned int val;
index 353f4dab62be492b0310ec497a1b8481d9bb63ea..3725fbb0defe541e3f1428015093797617491280 100644 (file)
@@ -85,7 +85,9 @@ struct recv_desc_bufs
 struct at91_private
 {
        struct mii_if_info mii;                 /* ethtool support */
-       struct at91_eth_data board_data;        /* board-specific configuration */
+       struct macb_platform_data board_data;   /* board-specific
+                                                * configuration (shared with
+                                                * macb for common data */
        struct clk *ether_clk;                  /* clock */
 
        /* PHY */
index a437b46e5490f8770707a5e4373c1bb4c9302fca..64d61461bdc78b65cac6d8995475909fbdd0bd98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Atmel MACB Ethernet Controller driver
+ * Cadence MACB/GEM Ethernet Controller driver
  *
  * Copyright (C) 2004-2006 Atmel Corporation
  *
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/dma-mapping.h>
+#include <linux/platform_data/macb.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
 
-#include <mach/board.h>
-#include <mach/cpu.h>
-
 #include "macb.h"
 
 #define RX_BUFFER_SIZE         128
@@ -60,9 +59,9 @@ static void __macb_set_hwaddr(struct macb *bp)
        u16 top;
 
        bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr));
-       macb_writel(bp, SA1B, bottom);
+       macb_or_gem_writel(bp, SA1B, bottom);
        top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));
-       macb_writel(bp, SA1T, top);
+       macb_or_gem_writel(bp, SA1T, top);
 }
 
 static void __init macb_get_hwaddr(struct macb *bp)
@@ -71,8 +70,8 @@ static void __init macb_get_hwaddr(struct macb *bp)
        u16 top;
        u8 addr[6];
 
-       bottom = macb_readl(bp, SA1B);
-       top = macb_readl(bp, SA1T);
+       bottom = macb_or_gem_readl(bp, SA1B);
+       top = macb_or_gem_readl(bp, SA1T);
 
        addr[0] = bottom & 0xff;
        addr[1] = (bottom >> 8) & 0xff;
@@ -84,7 +83,7 @@ static void __init macb_get_hwaddr(struct macb *bp)
        if (is_valid_ether_addr(addr)) {
                memcpy(bp->dev->dev_addr, addr, sizeof(addr));
        } else {
-               dev_info(&bp->pdev->dev, "invalid hw address, using random\n");
+               netdev_info(bp->dev, "invalid hw address, using random\n");
                random_ether_addr(bp->dev->dev_addr);
        }
 }
@@ -178,11 +177,12 @@ static void macb_handle_link_change(struct net_device *dev)
 
        if (status_change) {
                if (phydev->link)
-                       printk(KERN_INFO "%s: link up (%d/%s)\n",
-                              dev->name, phydev->speed,
-                              DUPLEX_FULL == phydev->duplex ? "Full":"Half");
+                       netdev_info(dev, "link up (%d/%s)\n",
+                                   phydev->speed,
+                                   phydev->duplex == DUPLEX_FULL ?
+                                   "Full" : "Half");
                else
-                       printk(KERN_INFO "%s: link down\n", dev->name);
+                       netdev_info(dev, "link down\n");
        }
 }
 
@@ -191,12 +191,12 @@ static int macb_mii_probe(struct net_device *dev)
 {
        struct macb *bp = netdev_priv(dev);
        struct phy_device *phydev;
-       struct eth_platform_data *pdata;
+       struct macb_platform_data *pdata;
        int ret;
 
        phydev = phy_find_first(bp->mii_bus);
        if (!phydev) {
-               printk (KERN_ERR "%s: no PHY found\n", dev->name);
+               netdev_err(dev, "no PHY found\n");
                return -1;
        }
 
@@ -209,7 +209,7 @@ static int macb_mii_probe(struct net_device *dev)
                                 PHY_INTERFACE_MODE_RMII :
                                 PHY_INTERFACE_MODE_MII);
        if (ret) {
-               printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+               netdev_err(dev, "Could not attach to PHY\n");
                return ret;
        }
 
@@ -228,7 +228,7 @@ static int macb_mii_probe(struct net_device *dev)
 
 static int macb_mii_init(struct macb *bp)
 {
-       struct eth_platform_data *pdata;
+       struct macb_platform_data *pdata;
        int err = -ENXIO, i;
 
        /* Enable management port */
@@ -285,8 +285,8 @@ err_out:
 static void macb_update_stats(struct macb *bp)
 {
        u32 __iomem *reg = bp->regs + MACB_PFR;
-       u32 *p = &bp->hw_stats.rx_pause_frames;
-       u32 *end = &bp->hw_stats.tx_pause_frames + 1;
+       u32 *p = &bp->hw_stats.macb.rx_pause_frames;
+       u32 *end = &bp->hw_stats.macb.tx_pause_frames + 1;
 
        WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4);
 
@@ -303,14 +303,13 @@ static void macb_tx(struct macb *bp)
        status = macb_readl(bp, TSR);
        macb_writel(bp, TSR, status);
 
-       dev_dbg(&bp->pdev->dev, "macb_tx status = %02lx\n",
-               (unsigned long)status);
+       netdev_dbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status);
 
        if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) {
                int i;
-               printk(KERN_ERR "%s: TX %s, resetting buffers\n",
-                       bp->dev->name, status & MACB_BIT(UND) ?
-                       "underrun" : "retry limit exceeded");
+               netdev_err(bp->dev, "TX %s, resetting buffers\n",
+                          status & MACB_BIT(UND) ?
+                          "underrun" : "retry limit exceeded");
 
                /* Transfer ongoing, disable transmitter, to avoid confusion */
                if (status & MACB_BIT(TGO))
@@ -369,8 +368,8 @@ static void macb_tx(struct macb *bp)
                if (!(bufstat & MACB_BIT(TX_USED)))
                        break;
 
-               dev_dbg(&bp->pdev->dev, "skb %u (data %p) TX complete\n",
-                       tail, skb->data);
+               netdev_dbg(bp->dev, "skb %u (data %p) TX complete\n",
+                          tail, skb->data);
                dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
                                 DMA_TO_DEVICE);
                bp->stats.tx_packets++;
@@ -395,8 +394,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
 
        len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl);
 
-       dev_dbg(&bp->pdev->dev, "macb_rx_frame frags %u - %u (len %u)\n",
-               first_frag, last_frag, len);
+       netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
+                  first_frag, last_frag, len);
 
        skb = dev_alloc_skb(len + RX_OFFSET);
        if (!skb) {
@@ -437,8 +436,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
 
        bp->stats.rx_packets++;
        bp->stats.rx_bytes += len;
-       dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n",
-               skb->len, skb->csum);
+       netdev_dbg(bp->dev, "received skb of length %u, csum: %08x\n",
+                  skb->len, skb->csum);
        netif_receive_skb(skb);
 
        return 0;
@@ -515,8 +514,8 @@ static int macb_poll(struct napi_struct *napi, int budget)
 
        work_done = 0;
 
-       dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n",
-               (unsigned long)status, budget);
+       netdev_dbg(bp->dev, "poll: status = %08lx, budget = %d\n",
+                  (unsigned long)status, budget);
 
        work_done = macb_rx(bp, budget);
        if (work_done < budget) {
@@ -565,8 +564,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                        macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
 
                        if (napi_schedule_prep(&bp->napi)) {
-                               dev_dbg(&bp->pdev->dev,
-                                       "scheduling RX softirq\n");
+                               netdev_dbg(bp->dev, "scheduling RX softirq\n");
                                __napi_schedule(&bp->napi);
                        }
                }
@@ -582,16 +580,19 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 
                if (status & MACB_BIT(ISR_ROVR)) {
                        /* We missed at least one packet */
-                       bp->hw_stats.rx_overruns++;
+                       if (macb_is_gem(bp))
+                               bp->hw_stats.gem.rx_overruns++;
+                       else
+                               bp->hw_stats.macb.rx_overruns++;
                }
 
                if (status & MACB_BIT(HRESP)) {
                        /*
-                        * TODO: Reset the hardware, and maybe move the printk
-                        * to a lower-priority context as well (work queue?)
+                        * TODO: Reset the hardware, and maybe move the
+                        * netdev_err to a lower-priority context as well
+                        * (work queue?)
                         */
-                       printk(KERN_ERR "%s: DMA bus error: HRESP not OK\n",
-                              dev->name);
+                       netdev_err(dev, "DMA bus error: HRESP not OK\n");
                }
 
                status = macb_readl(bp, ISR);
@@ -626,16 +627,12 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        unsigned long flags;
 
 #ifdef DEBUG
-       int i;
-       dev_dbg(&bp->pdev->dev,
-               "start_xmit: len %u head %p data %p tail %p end %p\n",
-               skb->len, skb->head, skb->data,
-               skb_tail_pointer(skb), skb_end_pointer(skb));
-       dev_dbg(&bp->pdev->dev,
-               "data:");
-       for (i = 0; i < 16; i++)
-               printk(" %02x", (unsigned int)skb->data[i]);
-       printk("\n");
+       netdev_dbg(bp->dev,
+                  "start_xmit: len %u head %p data %p tail %p end %p\n",
+                  skb->len, skb->head, skb->data,
+                  skb_tail_pointer(skb), skb_end_pointer(skb));
+       print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_OFFSET, 16, 1,
+                      skb->data, 16, true);
 #endif
 
        len = skb->len;
@@ -645,21 +642,20 @@ 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_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",
-                       bp->tx_head, bp->tx_tail);
+               netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n");
+               netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n",
+                          bp->tx_head, bp->tx_tail);
                return NETDEV_TX_BUSY;
        }
 
        entry = bp->tx_head;
-       dev_dbg(&bp->pdev->dev, "Allocated ring entry %u\n", entry);
+       netdev_dbg(bp->dev, "Allocated ring entry %u\n", entry);
        mapping = dma_map_single(&bp->pdev->dev, skb->data,
                                 len, DMA_TO_DEVICE);
        bp->tx_skb[entry].skb = skb;
        bp->tx_skb[entry].mapping = mapping;
-       dev_dbg(&bp->pdev->dev, "Mapped skb data %p to DMA addr %08lx\n",
-               skb->data, (unsigned long)mapping);
+       netdev_dbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
+                  skb->data, (unsigned long)mapping);
 
        ctrl = MACB_BF(TX_FRMLEN, len);
        ctrl |= MACB_BIT(TX_LAST);
@@ -723,27 +719,27 @@ static int macb_alloc_consistent(struct macb *bp)
                                         &bp->rx_ring_dma, GFP_KERNEL);
        if (!bp->rx_ring)
                goto out_err;
-       dev_dbg(&bp->pdev->dev,
-               "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
-               size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
+       netdev_dbg(bp->dev,
+                  "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
+                  size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
 
        size = TX_RING_BYTES;
        bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
                                         &bp->tx_ring_dma, GFP_KERNEL);
        if (!bp->tx_ring)
                goto out_err;
-       dev_dbg(&bp->pdev->dev,
-               "Allocated TX ring of %d bytes at %08lx (mapped %p)\n",
-               size, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
+       netdev_dbg(bp->dev,
+                  "Allocated TX ring of %d bytes at %08lx (mapped %p)\n",
+                  size, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
 
        size = RX_RING_SIZE * RX_BUFFER_SIZE;
        bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
                                            &bp->rx_buffers_dma, GFP_KERNEL);
        if (!bp->rx_buffers)
                goto out_err;
-       dev_dbg(&bp->pdev->dev,
-               "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n",
-               size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers);
+       netdev_dbg(bp->dev,
+                  "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n",
+                  size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers);
 
        return 0;
 
@@ -797,6 +793,84 @@ static void macb_reset_hw(struct macb *bp)
        macb_readl(bp, ISR);
 }
 
+static u32 gem_mdc_clk_div(struct macb *bp)
+{
+       u32 config;
+       unsigned long pclk_hz = clk_get_rate(bp->pclk);
+
+       if (pclk_hz <= 20000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV8);
+       else if (pclk_hz <= 40000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV16);
+       else if (pclk_hz <= 80000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV32);
+       else if (pclk_hz <= 120000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV48);
+       else if (pclk_hz <= 160000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV64);
+       else
+               config = GEM_BF(CLK, GEM_CLK_DIV96);
+
+       return config;
+}
+
+static u32 macb_mdc_clk_div(struct macb *bp)
+{
+       u32 config;
+       unsigned long pclk_hz;
+
+       if (macb_is_gem(bp))
+               return gem_mdc_clk_div(bp);
+
+       pclk_hz = clk_get_rate(bp->pclk);
+       if (pclk_hz <= 20000000)
+               config = MACB_BF(CLK, MACB_CLK_DIV8);
+       else if (pclk_hz <= 40000000)
+               config = MACB_BF(CLK, MACB_CLK_DIV16);
+       else if (pclk_hz <= 80000000)
+               config = MACB_BF(CLK, MACB_CLK_DIV32);
+       else
+               config = MACB_BF(CLK, MACB_CLK_DIV64);
+
+       return config;
+}
+
+/*
+ * Get the DMA bus width field of the network configuration register that we
+ * should program.  We find the width from decoding the design configuration
+ * register to find the maximum supported data bus width.
+ */
+static u32 macb_dbw(struct macb *bp)
+{
+       if (!macb_is_gem(bp))
+               return 0;
+
+       switch (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1))) {
+       case 4:
+               return GEM_BF(DBW, GEM_DBW128);
+       case 2:
+               return GEM_BF(DBW, GEM_DBW64);
+       case 1:
+       default:
+               return GEM_BF(DBW, GEM_DBW32);
+       }
+}
+
+/*
+ * Configure the receive DMA engine to use the correct receive buffer size.
+ * This is a configurable parameter for GEM.
+ */
+static void macb_configure_dma(struct macb *bp)
+{
+       u32 dmacfg;
+
+       if (macb_is_gem(bp)) {
+               dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
+               dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64);
+               gem_writel(bp, DMACFG, dmacfg);
+       }
+}
+
 static void macb_init_hw(struct macb *bp)
 {
        u32 config;
@@ -804,7 +878,7 @@ static void macb_init_hw(struct macb *bp)
        macb_reset_hw(bp);
        __macb_set_hwaddr(bp);
 
-       config = macb_readl(bp, NCFGR) & MACB_BF(CLK, -1L);
+       config = macb_mdc_clk_div(bp);
        config |= MACB_BIT(PAE);                /* PAuse Enable */
        config |= MACB_BIT(DRFCS);              /* Discard Rx FCS */
        config |= MACB_BIT(BIG);                /* Receive oversized frames */
@@ -812,8 +886,11 @@ static void macb_init_hw(struct macb *bp)
                config |= MACB_BIT(CAF);        /* Copy All Frames */
        if (!(bp->dev->flags & IFF_BROADCAST))
                config |= MACB_BIT(NBC);        /* No BroadCast */
+       config |= macb_dbw(bp);
        macb_writel(bp, NCFGR, config);
 
+       macb_configure_dma(bp);
+
        /* Initialize TX and RX buffers */
        macb_writel(bp, RBQP, bp->rx_ring_dma);
        macb_writel(bp, TBQP, bp->tx_ring_dma);
@@ -909,8 +986,8 @@ static void macb_sethashtable(struct net_device *dev)
                mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
        }
 
-       macb_writel(bp, HRB, mc_filter[0]);
-       macb_writel(bp, HRT, mc_filter[1]);
+       macb_or_gem_writel(bp, HRB, mc_filter[0]);
+       macb_or_gem_writel(bp, HRT, mc_filter[1]);
 }
 
 /*
@@ -932,8 +1009,8 @@ static void macb_set_rx_mode(struct net_device *dev)
 
        if (dev->flags & IFF_ALLMULTI) {
                /* Enable all multicast mode */
-               macb_writel(bp, HRB, -1);
-               macb_writel(bp, HRT, -1);
+               macb_or_gem_writel(bp, HRB, -1);
+               macb_or_gem_writel(bp, HRT, -1);
                cfg |= MACB_BIT(NCFGR_MTI);
        } else if (!netdev_mc_empty(dev)) {
                /* Enable specific multicasts */
@@ -941,8 +1018,8 @@ static void macb_set_rx_mode(struct net_device *dev)
                cfg |= MACB_BIT(NCFGR_MTI);
        } else if (dev->flags & (~IFF_ALLMULTI)) {
                /* Disable all multicast mode */
-               macb_writel(bp, HRB, 0);
-               macb_writel(bp, HRT, 0);
+               macb_or_gem_writel(bp, HRB, 0);
+               macb_or_gem_writel(bp, HRT, 0);
                cfg &= ~MACB_BIT(NCFGR_MTI);
        }
 
@@ -954,7 +1031,7 @@ static int macb_open(struct net_device *dev)
        struct macb *bp = netdev_priv(dev);
        int err;
 
-       dev_dbg(&bp->pdev->dev, "open\n");
+       netdev_dbg(bp->dev, "open\n");
 
        /* if the phy is not yet register, retry later*/
        if (!bp->phy_dev)
@@ -965,9 +1042,8 @@ static int macb_open(struct net_device *dev)
 
        err = macb_alloc_consistent(bp);
        if (err) {
-               printk(KERN_ERR
-                      "%s: Unable to allocate DMA memory (error %d)\n",
-                      dev->name, err);
+               netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
+                          err);
                return err;
        }
 
@@ -1005,11 +1081,62 @@ static int macb_close(struct net_device *dev)
        return 0;
 }
 
+static void gem_update_stats(struct macb *bp)
+{
+       u32 __iomem *reg = bp->regs + GEM_OTX;
+       u32 *p = &bp->hw_stats.gem.tx_octets_31_0;
+       u32 *end = &bp->hw_stats.gem.rx_udp_checksum_errors + 1;
+
+       for (; p < end; p++, reg++)
+               *p += __raw_readl(reg);
+}
+
+static struct net_device_stats *gem_get_stats(struct macb *bp)
+{
+       struct gem_stats *hwstat = &bp->hw_stats.gem;
+       struct net_device_stats *nstat = &bp->stats;
+
+       gem_update_stats(bp);
+
+       nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors +
+                           hwstat->rx_alignment_errors +
+                           hwstat->rx_resource_errors +
+                           hwstat->rx_overruns +
+                           hwstat->rx_oversize_frames +
+                           hwstat->rx_jabbers +
+                           hwstat->rx_undersized_frames +
+                           hwstat->rx_length_field_frame_errors);
+       nstat->tx_errors = (hwstat->tx_late_collisions +
+                           hwstat->tx_excessive_collisions +
+                           hwstat->tx_underrun +
+                           hwstat->tx_carrier_sense_errors);
+       nstat->multicast = hwstat->rx_multicast_frames;
+       nstat->collisions = (hwstat->tx_single_collision_frames +
+                            hwstat->tx_multiple_collision_frames +
+                            hwstat->tx_excessive_collisions);
+       nstat->rx_length_errors = (hwstat->rx_oversize_frames +
+                                  hwstat->rx_jabbers +
+                                  hwstat->rx_undersized_frames +
+                                  hwstat->rx_length_field_frame_errors);
+       nstat->rx_over_errors = hwstat->rx_resource_errors;
+       nstat->rx_crc_errors = hwstat->rx_frame_check_sequence_errors;
+       nstat->rx_frame_errors = hwstat->rx_alignment_errors;
+       nstat->rx_fifo_errors = hwstat->rx_overruns;
+       nstat->tx_aborted_errors = hwstat->tx_excessive_collisions;
+       nstat->tx_carrier_errors = hwstat->tx_carrier_sense_errors;
+       nstat->tx_fifo_errors = hwstat->tx_underrun;
+
+       return nstat;
+}
+
 static struct net_device_stats *macb_get_stats(struct net_device *dev)
 {
        struct macb *bp = netdev_priv(dev);
        struct net_device_stats *nstat = &bp->stats;
-       struct macb_stats *hwstat = &bp->hw_stats;
+       struct macb_stats *hwstat = &bp->hw_stats.macb;
+
+       if (macb_is_gem(bp))
+               return gem_get_stats(bp);
 
        /* read stats from hardware */
        macb_update_stats(bp);
@@ -1119,12 +1246,11 @@ static const struct net_device_ops macb_netdev_ops = {
 
 static int __init macb_probe(struct platform_device *pdev)
 {
-       struct eth_platform_data *pdata;
+       struct macb_platform_data *pdata;
        struct resource *regs;
        struct net_device *dev;
        struct macb *bp;
        struct phy_device *phydev;
-       unsigned long pclk_hz;
        u32 config;
        int err = -ENXIO;
 
@@ -1152,28 +1278,19 @@ static int __init macb_probe(struct platform_device *pdev)
 
        spin_lock_init(&bp->lock);
 
-#if defined(CONFIG_ARCH_AT91)
-       bp->pclk = clk_get(&pdev->dev, "macb_clk");
+       bp->pclk = clk_get(&pdev->dev, "pclk");
        if (IS_ERR(bp->pclk)) {
                dev_err(&pdev->dev, "failed to get macb_clk\n");
                goto err_out_free_dev;
        }
        clk_enable(bp->pclk);
-#else
-       bp->pclk = clk_get(&pdev->dev, "pclk");
-       if (IS_ERR(bp->pclk)) {
-               dev_err(&pdev->dev, "failed to get pclk\n");
-               goto err_out_free_dev;
-       }
+
        bp->hclk = clk_get(&pdev->dev, "hclk");
        if (IS_ERR(bp->hclk)) {
                dev_err(&pdev->dev, "failed to get hclk\n");
                goto err_out_put_pclk;
        }
-
-       clk_enable(bp->pclk);
        clk_enable(bp->hclk);
-#endif
 
        bp->regs = ioremap(regs->start, resource_size(regs));
        if (!bp->regs) {
@@ -1185,9 +1302,8 @@ static int __init macb_probe(struct platform_device *pdev)
        dev->irq = platform_get_irq(pdev, 0);
        err = request_irq(dev->irq, macb_interrupt, 0, dev->name, dev);
        if (err) {
-               printk(KERN_ERR
-                      "%s: Unable to request IRQ %d (error %d)\n",
-                      dev->name, dev->irq, err);
+               dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n",
+                       dev->irq, err);
                goto err_out_iounmap;
        }
 
@@ -1198,15 +1314,8 @@ static int __init macb_probe(struct platform_device *pdev)
        dev->base_addr = regs->start;
 
        /* Set MII management clock divider */
-       pclk_hz = clk_get_rate(bp->pclk);
-       if (pclk_hz <= 20000000)
-               config = MACB_BF(CLK, MACB_CLK_DIV8);
-       else if (pclk_hz <= 40000000)
-               config = MACB_BF(CLK, MACB_CLK_DIV16);
-       else if (pclk_hz <= 80000000)
-               config = MACB_BF(CLK, MACB_CLK_DIV32);
-       else
-               config = MACB_BF(CLK, MACB_CLK_DIV64);
+       config = macb_mdc_clk_div(bp);
+       config |= macb_dbw(bp);
        macb_writel(bp, NCFGR, config);
 
        macb_get_hwaddr(bp);
@@ -1214,15 +1323,16 @@ static int __init macb_probe(struct platform_device *pdev)
 
        if (pdata && pdata->is_rmii)
 #if defined(CONFIG_ARCH_AT91)
-               macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) );
+               macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) |
+                                              MACB_BIT(CLKEN)));
 #else
-               macb_writel(bp, USRIO, 0);
+               macb_or_gem_writel(bp, USRIO, 0);
 #endif
        else
 #if defined(CONFIG_ARCH_AT91)
-               macb_writel(bp, USRIO, MACB_BIT(CLKEN));
+               macb_or_gem_writel(bp, USRIO, MACB_BIT(CLKEN));
 #else
-               macb_writel(bp, USRIO, MACB_BIT(MII));
+               macb_or_gem_writel(bp, USRIO, MACB_BIT(MII));
 #endif
 
        bp->tx_pending = DEF_TX_RING_PENDING;
@@ -1239,13 +1349,13 @@ static int __init macb_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, dev);
 
-       printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d (%pM)\n",
-              dev->name, dev->base_addr, dev->irq, dev->dev_addr);
+       netdev_info(dev, "Cadence %s at 0x%08lx irq %d (%pM)\n",
+                   macb_is_gem(bp) ? "GEM" : "MACB", dev->base_addr,
+                   dev->irq, dev->dev_addr);
 
        phydev = bp->phy_dev;
-       printk(KERN_INFO "%s: attached PHY driver [%s] "
-               "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name,
-               phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
+       netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+                   phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
 
        return 0;
 
@@ -1256,14 +1366,10 @@ err_out_free_irq:
 err_out_iounmap:
        iounmap(bp->regs);
 err_out_disable_clocks:
-#ifndef CONFIG_ARCH_AT91
        clk_disable(bp->hclk);
        clk_put(bp->hclk);
-#endif
        clk_disable(bp->pclk);
-#ifndef CONFIG_ARCH_AT91
 err_out_put_pclk:
-#endif
        clk_put(bp->pclk);
 err_out_free_dev:
        free_netdev(dev);
@@ -1289,10 +1395,8 @@ static int __exit macb_remove(struct platform_device *pdev)
                unregister_netdev(dev);
                free_irq(dev->irq, dev);
                iounmap(bp->regs);
-#ifndef CONFIG_ARCH_AT91
                clk_disable(bp->hclk);
                clk_put(bp->hclk);
-#endif
                clk_disable(bp->pclk);
                clk_put(bp->pclk);
                free_netdev(dev);
@@ -1310,9 +1414,7 @@ static int macb_suspend(struct platform_device *pdev, pm_message_t state)
 
        netif_device_detach(netdev);
 
-#ifndef CONFIG_ARCH_AT91
        clk_disable(bp->hclk);
-#endif
        clk_disable(bp->pclk);
 
        return 0;
@@ -1324,9 +1426,7 @@ static int macb_resume(struct platform_device *pdev)
        struct macb *bp = netdev_priv(netdev);
 
        clk_enable(bp->pclk);
-#ifndef CONFIG_ARCH_AT91
        clk_enable(bp->hclk);
-#endif
 
        netif_device_attach(netdev);
 
@@ -1361,6 +1461,6 @@ module_init(macb_init);
 module_exit(macb_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
+MODULE_DESCRIPTION("Cadence MACB/GEM Ethernet driver");
 MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
 MODULE_ALIAS("platform:macb");
index d3212f6db70325a53917b380e4f4ab05f8abd9b4..193107884a5af4c2e2d7eb1a787d557f5fb2aa67 100644 (file)
 #define MACB_TPQ                               0x00bc
 #define MACB_USRIO                             0x00c0
 #define MACB_WOL                               0x00c4
+#define MACB_MID                               0x00fc
+
+/* GEM register offsets. */
+#define GEM_NCFGR                              0x0004
+#define GEM_USRIO                              0x000c
+#define GEM_DMACFG                             0x0010
+#define GEM_HRB                                        0x0080
+#define GEM_HRT                                        0x0084
+#define GEM_SA1B                               0x0088
+#define GEM_SA1T                               0x008C
+#define GEM_OTX                                        0x0100
+#define GEM_DCFG1                              0x0280
+#define GEM_DCFG2                              0x0284
+#define GEM_DCFG3                              0x0288
+#define GEM_DCFG4                              0x028c
+#define GEM_DCFG5                              0x0290
+#define GEM_DCFG6                              0x0294
+#define GEM_DCFG7                              0x0298
 
 /* Bitfields in NCR */
 #define MACB_LB_OFFSET                         0
 #define MACB_IRXFCS_OFFSET                     19
 #define MACB_IRXFCS_SIZE                       1
 
+/* GEM specific NCFGR bitfields. */
+#define GEM_CLK_OFFSET                         18
+#define GEM_CLK_SIZE                           3
+#define GEM_DBW_OFFSET                         21
+#define GEM_DBW_SIZE                           2
+
+/* Constants for data bus width. */
+#define GEM_DBW32                              0
+#define GEM_DBW64                              1
+#define GEM_DBW128                             2
+
+/* Bitfields in DMACFG. */
+#define GEM_RXBS_OFFSET                                16
+#define GEM_RXBS_SIZE                          8
+
 /* Bitfields in NSR */
 #define MACB_NSR_LINK_OFFSET                   0
 #define MACB_NSR_LINK_SIZE                     1
 #define MACB_WOL_MTI_OFFSET                    19
 #define MACB_WOL_MTI_SIZE                      1
 
+/* Bitfields in MID */
+#define MACB_IDNUM_OFFSET                      16
+#define MACB_IDNUM_SIZE                                16
+#define MACB_REV_OFFSET                                0
+#define MACB_REV_SIZE                          16
+
+/* Bitfields in DCFG1. */
+#define GEM_DBWDEF_OFFSET                      25
+#define GEM_DBWDEF_SIZE                                3
+
 /* Constants for CLK */
 #define MACB_CLK_DIV8                          0
 #define MACB_CLK_DIV16                         1
 #define MACB_CLK_DIV32                         2
 #define MACB_CLK_DIV64                         3
 
+/* GEM specific constants for CLK. */
+#define GEM_CLK_DIV8                           0
+#define GEM_CLK_DIV16                          1
+#define GEM_CLK_DIV32                          2
+#define GEM_CLK_DIV48                          3
+#define GEM_CLK_DIV64                          4
+#define GEM_CLK_DIV96                          5
+
 /* Constants for MAN register */
 #define MACB_MAN_SOF                           1
 #define MACB_MAN_WRITE                         1
                    << MACB_##name##_OFFSET))           \
         | MACB_BF(name,value))
 
+#define GEM_BIT(name)                                  \
+       (1 << GEM_##name##_OFFSET)
+#define GEM_BF(name, value)                            \
+       (((value) & ((1 << GEM_##name##_SIZE) - 1))     \
+        << GEM_##name##_OFFSET)
+#define GEM_BFEXT(name, value)\
+       (((value) >> GEM_##name##_OFFSET)               \
+        & ((1 << GEM_##name##_SIZE) - 1))
+#define GEM_BFINS(name, value, old)                    \
+       (((old) & ~(((1 << GEM_##name##_SIZE) - 1)      \
+                   << GEM_##name##_OFFSET))            \
+        | GEM_BF(name, value))
+
 /* Register access macros */
 #define macb_readl(port,reg)                           \
        __raw_readl((port)->regs + MACB_##reg)
 #define macb_writel(port,reg,value)                    \
        __raw_writel((value), (port)->regs + MACB_##reg)
+#define gem_readl(port, reg)                           \
+       __raw_readl((port)->regs + GEM_##reg)
+#define gem_writel(port, reg, value)                   \
+       __raw_writel((value), (port)->regs + GEM_##reg)
+
+/*
+ * Conditional GEM/MACB macros.  These perform the operation to the correct
+ * register dependent on whether the device is a GEM or a MACB.  For registers
+ * and bitfields that are common across both devices, use macb_{read,write}l
+ * to avoid the cost of the conditional.
+ */
+#define macb_or_gem_writel(__bp, __reg, __value) \
+       ({ \
+               if (macb_is_gem((__bp))) \
+                       gem_writel((__bp), __reg, __value); \
+               else \
+                       macb_writel((__bp), __reg, __value); \
+       })
+
+#define macb_or_gem_readl(__bp, __reg) \
+       ({ \
+               u32 __v; \
+               if (macb_is_gem((__bp))) \
+                       __v = gem_readl((__bp), __reg); \
+               else \
+                       __v = macb_readl((__bp), __reg); \
+               __v; \
+       })
 
 struct dma_desc {
        u32     addr;
@@ -358,6 +450,54 @@ struct macb_stats {
        u32     tx_pause_frames;
 };
 
+struct gem_stats {
+       u32     tx_octets_31_0;
+       u32     tx_octets_47_32;
+       u32     tx_frames;
+       u32     tx_broadcast_frames;
+       u32     tx_multicast_frames;
+       u32     tx_pause_frames;
+       u32     tx_64_byte_frames;
+       u32     tx_65_127_byte_frames;
+       u32     tx_128_255_byte_frames;
+       u32     tx_256_511_byte_frames;
+       u32     tx_512_1023_byte_frames;
+       u32     tx_1024_1518_byte_frames;
+       u32     tx_greater_than_1518_byte_frames;
+       u32     tx_underrun;
+       u32     tx_single_collision_frames;
+       u32     tx_multiple_collision_frames;
+       u32     tx_excessive_collisions;
+       u32     tx_late_collisions;
+       u32     tx_deferred_frames;
+       u32     tx_carrier_sense_errors;
+       u32     rx_octets_31_0;
+       u32     rx_octets_47_32;
+       u32     rx_frames;
+       u32     rx_broadcast_frames;
+       u32     rx_multicast_frames;
+       u32     rx_pause_frames;
+       u32     rx_64_byte_frames;
+       u32     rx_65_127_byte_frames;
+       u32     rx_128_255_byte_frames;
+       u32     rx_256_511_byte_frames;
+       u32     rx_512_1023_byte_frames;
+       u32     rx_1024_1518_byte_frames;
+       u32     rx_greater_than_1518_byte_frames;
+       u32     rx_undersized_frames;
+       u32     rx_oversize_frames;
+       u32     rx_jabbers;
+       u32     rx_frame_check_sequence_errors;
+       u32     rx_length_field_frame_errors;
+       u32     rx_symbol_errors;
+       u32     rx_alignment_errors;
+       u32     rx_resource_errors;
+       u32     rx_overruns;
+       u32     rx_ip_header_checksum_errors;
+       u32     rx_tcp_checksum_errors;
+       u32     rx_udp_checksum_errors;
+};
+
 struct macb {
        void __iomem            *regs;
 
@@ -376,7 +516,10 @@ struct macb {
        struct net_device       *dev;
        struct napi_struct      napi;
        struct net_device_stats stats;
-       struct macb_stats       hw_stats;
+       union {
+               struct macb_stats       macb;
+               struct gem_stats        gem;
+       }                       hw_stats;
 
        dma_addr_t              rx_ring_dma;
        dma_addr_t              tx_ring_dma;
@@ -391,4 +534,9 @@ struct macb {
        unsigned int            duplex;
 };
 
+static inline bool macb_is_gem(struct macb *bp)
+{
+       return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
+}
+
 #endif /* _MACB_H */
index 1cf671643d1fc13d508c13102b5424c77f3ddb1e..c520cfd3b29805440508acff0a8748b5956fee11 100644 (file)
@@ -7,8 +7,7 @@ config NET_VENDOR_FREESCALE
        default y
        depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
                   M523x || M527x || M5272 || M528x || M520x || M532x || \
-                  ARCH_MXC || ARCH_MXS || \
-                  (PPC_MPC52xx && PPC_BESTCOMM)
+                  ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 61029dc7fa6f82534641e03c2d432466a8a76165..76213162fbe32499869470472243b96a003afbb8 100644 (file)
@@ -5,7 +5,11 @@
 config NET_VENDOR_INTEL
        bool "Intel devices"
        default y
-       depends on PCI || PCI_MSI
+       depends on PCI || PCI_MSI || ISA || ISA_DMA_API || ARM || \
+                  ARCH_ACORN || MCA || MCA_LEGACY || SNI_RM || SUN3 || \
+                  GSC || BVME6000 || MVME16x || ARCH_ENP2611 || \
+                  (ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR) || \
+                  EXPERIMENTAL
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index db95731863d75bf470ce660b13de951f50670eed..00fcd39ad666b6c289379e401800438347952dd7 100644 (file)
@@ -442,12 +442,14 @@ static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter,
 
 int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter)
 {
+#ifdef CONFIG_PCI_IOV
        int i;
        for (i = 0; i < adapter->num_vfs; i++) {
                if (adapter->vfinfo[i].vfdev->dev_flags &
                                PCI_DEV_FLAGS_ASSIGNED)
                        return true;
        }
+#endif
        return false;
 }
 
index 4a5d8897faab47ec93358c7a7d16c4b44d983b83..df04f1a3857c96e5e16b4098580d2904c5c33a2e 100644 (file)
@@ -42,11 +42,11 @@ int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
 int ixgbe_ndo_get_vf_config(struct net_device *netdev,
                            int vf, struct ifla_vf_info *ivi);
 void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
-#ifdef CONFIG_PCI_IOV
 void ixgbe_disable_sriov(struct ixgbe_adapter *adapter);
+int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter);
+#ifdef CONFIG_PCI_IOV
 void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
                        const struct ixgbe_info *ii);
-int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter);
 #endif
 
 
index 6bb2b9506cadfde73ddef809bc0fcf78dd202b0a..0b3567ab812151f00210544cc805815b0953a90d 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
 
 #include <asm/checksum.h>
 
index cbd026f3bc57f5ee164bc68d94bfd8197d6b1fe7..7803efa46eb26b4b9fb5465ea1cb1df15d26d8ed 100644 (file)
@@ -50,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.29"
+#define DRV_VERSION            "1.30"
 
 /*
  * The Yukon II chipset takes 64 bit command blocks (called list elements)
@@ -68,7 +68,7 @@
 #define MAX_SKB_TX_LE  (2 + (sizeof(dma_addr_t)/sizeof(u32))*(MAX_SKB_FRAGS+1))
 #define TX_MIN_PENDING         (MAX_SKB_TX_LE+1)
 #define TX_MAX_PENDING         1024
-#define TX_DEF_PENDING         127
+#define TX_DEF_PENDING         63
 
 #define TX_WATCHDOG            (5 * HZ)
 #define NAPI_WEIGHT            64
@@ -366,17 +366,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
                                gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec);
                        }
                } else {
-                       if (hw->chip_id >= CHIP_ID_YUKON_OPT) {
-                               u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2);
-
-                               /* enable PHY Reverse Auto-Negotiation */
-                               ctrl2 |= 1u << 13;
-
-                               /* Write PHY changes (SW-reset must follow) */
-                               gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2);
-                       }
-
-
                        /* disable energy detect */
                        ctrl &= ~PHY_M_PC_EN_DET_MSK;
 
@@ -880,6 +869,7 @@ static void sky2_wol_init(struct sky2_port *sky2)
 
        /* block receiver */
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+       sky2_read32(hw, B0_CTST);
 }
 
 static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
@@ -1285,6 +1275,14 @@ static void rx_set_checksum(struct sky2_port *sky2)
                     ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
 }
 
+/*
+ * Fixed initial key as seed to RSS.
+ */
+static const uint32_t rss_init_key[10] = {
+       0x7c3351da, 0x51c5cf4e, 0x44adbdd1, 0xe8d38d18, 0x48897c43,
+       0xb1d60e7e, 0x6a3dd760, 0x01a2e453, 0x16f46f13, 0x1a0e7b30
+};
+
 /* Enable/disable receive hash calculation (RSS) */
 static void rx_set_rss(struct net_device *dev, u32 features)
 {
@@ -1300,12 +1298,9 @@ static void rx_set_rss(struct net_device *dev, u32 features)
 
        /* Program RSS initial values */
        if (features & NETIF_F_RXHASH) {
-               u32 key[nkeys];
-
-               get_random_bytes(key, nkeys * sizeof(u32));
                for (i = 0; i < nkeys; i++)
                        sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4),
-                                    key[i]);
+                                    rss_init_key[i]);
 
                /* Need to turn on (undocumented) flag to make hashing work  */
                sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T),
@@ -1728,6 +1723,8 @@ static int sky2_setup_irq(struct sky2_hw *hw, const char *name)
        if (err)
                dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
        else {
+               hw->flags |= SKY2_HW_IRQ_SETUP;
+
                napi_enable(&hw->napi);
                sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
                sky2_read32(hw, B0_IMSK);
@@ -1738,7 +1735,7 @@ static int sky2_setup_irq(struct sky2_hw *hw, const char *name)
 
 
 /* Bring up network interface. */
-static int sky2_up(struct net_device *dev)
+static int sky2_open(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
@@ -1758,6 +1755,11 @@ static int sky2_up(struct net_device *dev)
 
        sky2_hw_up(sky2);
 
+       if (hw->chip_id == CHIP_ID_YUKON_OPT ||
+           hw->chip_id == CHIP_ID_YUKON_PRM ||
+           hw->chip_id == CHIP_ID_YUKON_OP_2)
+               imask |= Y2_IS_PHY_QLNK;        /* enable PHY Quick Link */
+
        /* Enable interrupts from phy/mac for port */
        imask = sky2_read32(hw, B0_IMSK);
        imask |= portirq_msk[port];
@@ -2051,6 +2053,8 @@ static void sky2_tx_reset(struct sky2_hw *hw, unsigned port)
 
        sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
        sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+
+       sky2_read32(hw, B0_CTST);
 }
 
 static void sky2_hw_down(struct sky2_port *sky2)
@@ -2101,7 +2105,7 @@ static void sky2_hw_down(struct sky2_port *sky2)
 }
 
 /* Network shutdown */
-static int sky2_down(struct net_device *dev)
+static int sky2_close(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
@@ -2112,15 +2116,22 @@ static int sky2_down(struct net_device *dev)
 
        netif_info(sky2, ifdown, dev, "disabling interface\n");
 
-       /* Disable port IRQ */
-       sky2_write32(hw, B0_IMSK,
-                    sky2_read32(hw, B0_IMSK) & ~portirq_msk[sky2->port]);
-       sky2_read32(hw, B0_IMSK);
-
        if (hw->ports == 1) {
+               sky2_write32(hw, B0_IMSK, 0);
+               sky2_read32(hw, B0_IMSK);
+
                napi_disable(&hw->napi);
                free_irq(hw->pdev->irq, hw);
+               hw->flags &= ~SKY2_HW_IRQ_SETUP;
        } else {
+               u32 imask;
+
+               /* Disable port IRQ */
+               imask  = sky2_read32(hw, B0_IMSK);
+               imask &= ~portirq_msk[sky2->port];
+               sky2_write32(hw, B0_IMSK, imask);
+               sky2_read32(hw, B0_IMSK);
+
                synchronize_irq(hw->pdev->irq);
                napi_synchronize(&hw->napi);
        }
@@ -2598,7 +2609,7 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
        if (netif_running(dev)) {
                sky2_tx_complete(sky2, last);
 
-               /* Wake unless it's detached, and called e.g. from sky2_down() */
+               /* Wake unless it's detached, and called e.g. from sky2_close() */
                if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
                        netif_wake_queue(dev);
        }
@@ -3269,7 +3280,6 @@ static void sky2_reset(struct sky2_hw *hw)
            hw->chip_id == CHIP_ID_YUKON_PRM ||
            hw->chip_id == CHIP_ID_YUKON_OP_2) {
                u16 reg;
-               u32 msk;
 
                if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) {
                        /* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */
@@ -3292,11 +3302,6 @@ static void sky2_reset(struct sky2_hw *hw)
                sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
                sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
 
-               /* enable PHY Quick Link */
-               msk = sky2_read32(hw, B0_IMSK);
-               msk |= Y2_IS_PHY_QLNK;
-               sky2_write32(hw, B0_IMSK, msk);
-
                /* check if PSMv2 was running before */
                reg = sky2_pci_read16(hw, PSM_CONFIG_REG3);
                if (reg & PCI_EXP_LNKCTL_ASPMC)
@@ -3394,7 +3399,7 @@ static void sky2_detach(struct net_device *dev)
                netif_tx_lock(dev);
                netif_device_detach(dev);       /* stop txq */
                netif_tx_unlock(dev);
-               sky2_down(dev);
+               sky2_close(dev);
        }
 }
 
@@ -3404,7 +3409,7 @@ static int sky2_reattach(struct net_device *dev)
        int err = 0;
 
        if (netif_running(dev)) {
-               err = sky2_up(dev);
+               err = sky2_open(dev);
                if (err) {
                        netdev_info(dev, "could not restart %d\n", err);
                        dev_close(dev);
@@ -3421,10 +3426,13 @@ static void sky2_all_down(struct sky2_hw *hw)
 {
        int i;
 
-       sky2_read32(hw, B0_IMSK);
-       sky2_write32(hw, B0_IMSK, 0);
-       synchronize_irq(hw->pdev->irq);
-       napi_disable(&hw->napi);
+       if (hw->flags & SKY2_HW_IRQ_SETUP) {
+               sky2_read32(hw, B0_IMSK);
+               sky2_write32(hw, B0_IMSK, 0);
+
+               synchronize_irq(hw->pdev->irq);
+               napi_disable(&hw->napi);
+       }
 
        for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
@@ -3457,11 +3465,12 @@ static void sky2_all_up(struct sky2_hw *hw)
                netif_wake_queue(dev);
        }
 
-       sky2_write32(hw, B0_IMSK, imask);
-       sky2_read32(hw, B0_IMSK);
-
-       sky2_read32(hw, B0_Y2_SP_LISR);
-       napi_enable(&hw->napi);
+       if (hw->flags & SKY2_HW_IRQ_SETUP) {
+               sky2_write32(hw, B0_IMSK, imask);
+               sky2_read32(hw, B0_IMSK);
+               sky2_read32(hw, B0_Y2_SP_LISR);
+               napi_enable(&hw->napi);
+       }
 }
 
 static void sky2_restart(struct work_struct *work)
@@ -4082,6 +4091,16 @@ static int sky2_set_coalesce(struct net_device *dev,
        return 0;
 }
 
+/*
+ * Hardware is limited to min of 128 and max of 2048 for ring size
+ * and  rounded up to next power of two
+ * to avoid division in modulus calclation
+ */
+static unsigned long roundup_ring_size(unsigned long pending)
+{
+       return max(128ul, roundup_pow_of_two(pending+1));
+}
+
 static void sky2_get_ringparam(struct net_device *dev,
                               struct ethtool_ringparam *ering)
 {
@@ -4109,7 +4128,7 @@ static int sky2_set_ringparam(struct net_device *dev,
 
        sky2->rx_pending = ering->rx_pending;
        sky2->tx_pending = ering->tx_pending;
-       sky2->tx_ring_size = roundup_pow_of_two(sky2->tx_pending+1);
+       sky2->tx_ring_size = roundup_ring_size(sky2->tx_pending);
 
        return sky2_reattach(dev);
 }
@@ -4567,7 +4586,7 @@ static int sky2_device_event(struct notifier_block *unused,
        struct net_device *dev = ptr;
        struct sky2_port *sky2 = netdev_priv(dev);
 
-       if (dev->netdev_ops->ndo_open != sky2_up || !sky2_debug)
+       if (dev->netdev_ops->ndo_open != sky2_open || !sky2_debug)
                return NOTIFY_DONE;
 
        switch (event) {
@@ -4632,8 +4651,8 @@ static __exit void sky2_debug_cleanup(void)
    not allowing netpoll on second port */
 static const struct net_device_ops sky2_netdev_ops[2] = {
   {
-       .ndo_open               = sky2_up,
-       .ndo_stop               = sky2_down,
+       .ndo_open               = sky2_open,
+       .ndo_stop               = sky2_close,
        .ndo_start_xmit         = sky2_xmit_frame,
        .ndo_do_ioctl           = sky2_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
@@ -4649,8 +4668,8 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
 #endif
   },
   {
-       .ndo_open               = sky2_up,
-       .ndo_stop               = sky2_down,
+       .ndo_open               = sky2_open,
+       .ndo_stop               = sky2_close,
        .ndo_start_xmit         = sky2_xmit_frame,
        .ndo_do_ioctl           = sky2_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
@@ -4703,7 +4722,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->tx_ring_size = roundup_pow_of_two(TX_DEF_PENDING+1);
+       sky2->tx_ring_size = roundup_ring_size(TX_DEF_PENDING);
        sky2->rx_pending = RX_DEF_PENDING;
 
        hw->dev[port] = dev;
index 0af31b8b5f106174b74c99cd124c758d95c71672..ff6f58bf822aa378ffa0975140733fa40bf41f5d 100644 (file)
@@ -2287,6 +2287,7 @@ struct sky2_hw {
 #define SKY2_HW_RSS_BROKEN     0x00000100
 #define SKY2_HW_VLAN_BROKEN     0x00000200
 #define SKY2_HW_RSS_CHKSUM     0x00000400      /* RSS requires chksum */
+#define SKY2_HW_IRQ_SETUP      0x00000800
 
        u8                   chip_id;
        u8                   chip_rev;
index b89c36dbf5b3ea7927fb46252819210bdd55ec26..c2df6c35860317e63a1473e2b69636bedaadc777 100644 (file)
@@ -581,6 +581,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                 * Packet is OK - process it.
                 */
                length = be32_to_cpu(cqe->byte_cnt);
+               length -= ring->fcs_del;
                ring->bytes += length;
                ring->packets++;
 
@@ -813,8 +814,11 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
        context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
 
        /* Cancel FCS removal if FW allows */
-       if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP)
+       if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP) {
                context->param3 |= cpu_to_be32(1 << 29);
+               ring->fcs_del = ETH_FCS_LEN;
+       } else
+               ring->fcs_del = 0;
 
        err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, context, qp, state);
        if (err) {
index 8fda331c65dfddd19a69da927444ec41be546da4..207b5add3ca848134ea44bf3fadd918ef2912c3f 100644 (file)
@@ -272,6 +272,7 @@ struct mlx4_en_rx_ring {
        u32 prod;
        u32 cons;
        u32 buf_size;
+       u8  fcs_del;
        void *buf;
        void *rx_info;
        unsigned long bytes;
index 4a6b9fd073b6330f5d2b693c322c0c5ea2bd5c29..eb836f770f500eb68ead520eacd5b5705f798e3f 100644 (file)
@@ -5,7 +5,10 @@
 config NET_VENDOR_NATSEMI
        bool "National Semi-conductor devices"
        default y
-       depends on MCA || MAC || MACH_JAZZ || PCI || XTENSA_PLATFORM_XT2000
+       depends on AMIGA_PCMCIA || ARM || EISA || EXPERIMENTAL || H8300 || \
+                  ISA || M32R || MAC || MACH_JAZZ || MACH_TX49XX || MCA || \
+                  MCA_LEGACY || MIPS || PCI || PCMCIA || SUPERH || \
+                  XTENSA_PLATFORM_XT2000 || ZORRO
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 1e37eb98c4e29265030dfe930b048d91ea384295..1c61d36e657070d16ecf921992e59a883bf574c3 100644 (file)
@@ -609,7 +609,7 @@ struct nv_ethtool_str {
 };
 
 static const struct nv_ethtool_str nv_estats_str[] = {
-       { "tx_bytes" },
+       { "tx_bytes" }, /* includes Ethernet FCS CRC */
        { "tx_zero_rexmt" },
        { "tx_one_rexmt" },
        { "tx_many_rexmt" },
@@ -637,7 +637,7 @@ static const struct nv_ethtool_str nv_estats_str[] = {
        /* version 2 stats */
        { "tx_deferral" },
        { "tx_packets" },
-       { "rx_bytes" },
+       { "rx_bytes" }, /* includes Ethernet FCS CRC */
        { "tx_pause" },
        { "rx_pause" },
        { "rx_drop_frame" },
@@ -649,7 +649,7 @@ static const struct nv_ethtool_str nv_estats_str[] = {
 };
 
 struct nv_ethtool_stats {
-       u64 tx_bytes;
+       u64 tx_bytes; /* should be ifconfig->tx_bytes + 4*tx_packets */
        u64 tx_zero_rexmt;
        u64 tx_one_rexmt;
        u64 tx_many_rexmt;
@@ -670,14 +670,14 @@ struct nv_ethtool_stats {
        u64 rx_unicast;
        u64 rx_multicast;
        u64 rx_broadcast;
-       u64 rx_packets;
+       u64 rx_packets; /* should be ifconfig->rx_packets */
        u64 rx_errors_total;
        u64 tx_errors_total;
 
        /* version 2 stats */
        u64 tx_deferral;
-       u64 tx_packets;
-       u64 rx_bytes;
+       u64 tx_packets; /* should be ifconfig->tx_packets */
+       u64 rx_bytes;   /* should be ifconfig->rx_bytes + 4*rx_packets */
        u64 tx_pause;
        u64 rx_pause;
        u64 rx_drop_frame;
@@ -1682,6 +1682,7 @@ static void nv_get_hw_stats(struct net_device *dev)
                np->estats.tx_pause += readl(base + NvRegTxPause);
                np->estats.rx_pause += readl(base + NvRegRxPause);
                np->estats.rx_drop_frame += readl(base + NvRegRxDropFrame);
+               np->estats.rx_errors_total += np->estats.rx_drop_frame;
        }
 
        if (np->driver_data & DEV_HAS_STATISTICS_V3) {
@@ -1705,12 +1706,22 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
        if (np->driver_data & (DEV_HAS_STATISTICS_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_STATISTICS_V3)) {
                nv_get_hw_stats(dev);
 
+               /*
+                * Note: because HW stats are not always available and
+                * for consistency reasons, the following ifconfig
+                * stats are managed by software: rx_bytes, tx_bytes,
+                * rx_packets and tx_packets. The related hardware
+                * stats reported by ethtool should be equivalent to
+                * these ifconfig stats, with 4 additional bytes per
+                * packet (Ethernet FCS CRC).
+                */
+
                /* copy to net_device stats */
-               dev->stats.tx_bytes = np->estats.tx_bytes;
                dev->stats.tx_fifo_errors = np->estats.tx_fifo_errors;
                dev->stats.tx_carrier_errors = np->estats.tx_carrier_errors;
                dev->stats.rx_crc_errors = np->estats.rx_crc_errors;
                dev->stats.rx_over_errors = np->estats.rx_over_errors;
+               dev->stats.rx_fifo_errors = np->estats.rx_drop_frame;
                dev->stats.rx_errors = np->estats.rx_errors_total;
                dev->stats.tx_errors = np->estats.tx_errors_total;
        }
@@ -2099,10 +2110,10 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* add fragments to entries count */
        for (i = 0; i < fragments; i++) {
-               u32 size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+               u32 frag_size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
 
-               entries += (size >> NV_TX2_TSO_MAX_SHIFT) +
-                          ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+               entries += (frag_size >> NV_TX2_TSO_MAX_SHIFT) +
+                          ((frag_size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
        }
 
        spin_lock_irqsave(&np->lock, flags);
@@ -2141,13 +2152,13 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* setup the fragments */
        for (i = 0; i < fragments; i++) {
                const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-               u32 size = skb_frag_size(frag);
+               u32 frag_size = skb_frag_size(frag);
                offset = 0;
 
                do {
                        prev_tx = put_tx;
                        prev_tx_ctx = np->put_tx_ctx;
-                       bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
+                       bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size;
                        np->put_tx_ctx->dma = skb_frag_dma_map(
                                                        &np->pci_dev->dev,
                                                        frag, offset,
@@ -2159,12 +2170,12 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 
                        offset += bcnt;
-                       size -= bcnt;
+                       frag_size -= bcnt;
                        if (unlikely(put_tx++ == np->last_tx.orig))
                                put_tx = np->first_tx.orig;
                        if (unlikely(np->put_tx_ctx++ == np->last_tx_ctx))
                                np->put_tx_ctx = np->first_tx_ctx;
-               } while (size);
+               } while (frag_size);
        }
 
        /* set last fragment flag  */
@@ -2213,10 +2224,10 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
 
        /* add fragments to entries count */
        for (i = 0; i < fragments; i++) {
-               u32 size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+               u32 frag_size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
 
-               entries += (size >> NV_TX2_TSO_MAX_SHIFT) +
-                          ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+               entries += (frag_size >> NV_TX2_TSO_MAX_SHIFT) +
+                          ((frag_size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
        }
 
        spin_lock_irqsave(&np->lock, flags);
@@ -2257,13 +2268,13 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
        /* setup the fragments */
        for (i = 0; i < fragments; i++) {
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-               u32 size = skb_frag_size(frag);
+               u32 frag_size = skb_frag_size(frag);
                offset = 0;
 
                do {
                        prev_tx = put_tx;
                        prev_tx_ctx = np->put_tx_ctx;
-                       bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
+                       bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size;
                        np->put_tx_ctx->dma = skb_frag_dma_map(
                                                        &np->pci_dev->dev,
                                                        frag, offset,
@@ -2276,12 +2287,12 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
                        put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 
                        offset += bcnt;
-                       size -= bcnt;
+                       frag_size -= bcnt;
                        if (unlikely(put_tx++ == np->last_tx.ex))
                                put_tx = np->first_tx.ex;
                        if (unlikely(np->put_tx_ctx++ == np->last_tx_ctx))
                                np->put_tx_ctx = np->first_tx_ctx;
-               } while (size);
+               } while (frag_size);
        }
 
        /* set last fragment flag  */
@@ -2374,13 +2385,8 @@ static int nv_tx_done(struct net_device *dev, int limit)
                if (np->desc_ver == DESC_VER_1) {
                        if (flags & NV_TX_LASTPACKET) {
                                if (flags & NV_TX_ERROR) {
-                                       if (flags & NV_TX_UNDERFLOW)
-                                               dev->stats.tx_fifo_errors++;
-                                       if (flags & NV_TX_CARRIERLOST)
-                                               dev->stats.tx_carrier_errors++;
                                        if ((flags & NV_TX_RETRYERROR) && !(flags & NV_TX_RETRYCOUNT_MASK))
                                                nv_legacybackoff_reseed(dev);
-                                       dev->stats.tx_errors++;
                                } else {
                                        dev->stats.tx_packets++;
                                        dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
@@ -2392,13 +2398,8 @@ static int nv_tx_done(struct net_device *dev, int limit)
                } else {
                        if (flags & NV_TX2_LASTPACKET) {
                                if (flags & NV_TX2_ERROR) {
-                                       if (flags & NV_TX2_UNDERFLOW)
-                                               dev->stats.tx_fifo_errors++;
-                                       if (flags & NV_TX2_CARRIERLOST)
-                                               dev->stats.tx_carrier_errors++;
                                        if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK))
                                                nv_legacybackoff_reseed(dev);
-                                       dev->stats.tx_errors++;
                                } else {
                                        dev->stats.tx_packets++;
                                        dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
@@ -2434,15 +2435,16 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit)
                nv_unmap_txskb(np, np->get_tx_ctx);
 
                if (flags & NV_TX2_LASTPACKET) {
-                       if (!(flags & NV_TX2_ERROR))
-                               dev->stats.tx_packets++;
-                       else {
+                       if (flags & NV_TX2_ERROR) {
                                if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) {
                                        if (np->driver_data & DEV_HAS_GEAR_MODE)
                                                nv_gear_backoff_reseed(dev);
                                        else
                                                nv_legacybackoff_reseed(dev);
                                }
+                       } else {
+                               dev->stats.tx_packets++;
+                               dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
                        }
 
                        dev_kfree_skb_any(np->get_tx_ctx->skb);
@@ -2636,7 +2638,6 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        if ((flags & NV_RX_ERROR_MASK) == NV_RX_ERROR4) {
                                                len = nv_getlen(dev, skb->data, len);
                                                if (len < 0) {
-                                                       dev->stats.rx_errors++;
                                                        dev_kfree_skb(skb);
                                                        goto next_pkt;
                                                }
@@ -2650,11 +2651,6 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        else {
                                                if (flags & NV_RX_MISSEDFRAME)
                                                        dev->stats.rx_missed_errors++;
-                                               if (flags & NV_RX_CRCERR)
-                                                       dev->stats.rx_crc_errors++;
-                                               if (flags & NV_RX_OVERFLOW)
-                                                       dev->stats.rx_over_errors++;
-                                               dev->stats.rx_errors++;
                                                dev_kfree_skb(skb);
                                                goto next_pkt;
                                        }
@@ -2670,7 +2666,6 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        if ((flags & NV_RX2_ERROR_MASK) == NV_RX2_ERROR4) {
                                                len = nv_getlen(dev, skb->data, len);
                                                if (len < 0) {
-                                                       dev->stats.rx_errors++;
                                                        dev_kfree_skb(skb);
                                                        goto next_pkt;
                                                }
@@ -2682,11 +2677,6 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        }
                                        /* the rest are hard errors */
                                        else {
-                                               if (flags & NV_RX2_CRCERR)
-                                                       dev->stats.rx_crc_errors++;
-                                               if (flags & NV_RX2_OVERFLOW)
-                                                       dev->stats.rx_over_errors++;
-                                               dev->stats.rx_errors++;
                                                dev_kfree_skb(skb);
                                                goto next_pkt;
                                        }
@@ -2787,7 +2777,6 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
                                __vlan_hwaccel_put_tag(skb, vid);
                        }
                        napi_gro_receive(&np->napi, skb);
-
                        dev->stats.rx_packets++;
                        dev->stats.rx_bytes += len;
                } else {
@@ -2962,11 +2951,11 @@ static void nv_set_multicast(struct net_device *dev)
                                struct netdev_hw_addr *ha;
 
                                netdev_for_each_mc_addr(ha, dev) {
-                                       unsigned char *addr = ha->addr;
+                                       unsigned char *hw_addr = ha->addr;
                                        u32 a, b;
 
-                                       a = le32_to_cpu(*(__le32 *) addr);
-                                       b = le16_to_cpu(*(__le16 *) (&addr[4]));
+                                       a = le32_to_cpu(*(__le32 *) hw_addr);
+                                       b = le16_to_cpu(*(__le16 *) (&hw_addr[4]));
                                        alwaysOn[0] &= a;
                                        alwaysOff[0] &= ~a;
                                        alwaysOn[1] &= b;
@@ -3398,7 +3387,8 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
 
        for (i = 0;; i++) {
                events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL;
-               writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus);
+               writel(events, base + NvRegMSIXIrqStatus);
+               netdev_dbg(dev, "tx irq events: %08x\n", events);
                if (!(events & np->irqmask))
                        break;
 
@@ -3509,7 +3499,8 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
 
        for (i = 0;; i++) {
                events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL;
-               writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
+               writel(events, base + NvRegMSIXIrqStatus);
+               netdev_dbg(dev, "rx irq events: %08x\n", events);
                if (!(events & np->irqmask))
                        break;
 
@@ -3553,7 +3544,8 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data)
 
        for (i = 0;; i++) {
                events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER;
-               writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus);
+               writel(events, base + NvRegMSIXIrqStatus);
+               netdev_dbg(dev, "irq events: %08x\n", events);
                if (!(events & np->irqmask))
                        break;
 
@@ -3617,10 +3609,10 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data)
 
        if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
                events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
-               writel(NVREG_IRQ_TIMER, base + NvRegIrqStatus);
+               writel(events & NVREG_IRQ_TIMER, base + NvRegIrqStatus);
        } else {
                events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK;
-               writel(NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus);
+               writel(events & NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus);
        }
        pci_push(base);
        if (!(events & NVREG_IRQ_TIMER))
@@ -4566,7 +4558,7 @@ static void nv_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *e
        struct fe_priv *np = netdev_priv(dev);
 
        /* update stats */
-       nv_do_stats_poll((unsigned long)dev);
+       nv_get_hw_stats(dev);
 
        memcpy(buffer, &np->estats, nv_get_sset_count(dev, ETH_SS_STATS)*sizeof(u64));
 }
index 9c075ea2682e2025043d1099ad3d2c70c20b00bf..9cb5f912e4891f5b832bb941bce6916c5248bdb6 100644 (file)
@@ -18,8 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <linux/module.h>      /* for __MODULE_STRING */
 #include "pch_gbe.h"
+#include <linux/module.h>      /* for __MODULE_STRING */
 
 #define OPTION_UNSET   -1
 #define OPTION_DISABLED 0
index 1fc01ca72b466095b682f209b266f7209f8d3ec1..4bf68cfef39072d607420c476160944888d5fa47 100644 (file)
@@ -940,7 +940,7 @@ static void r6040_multicast_list(struct net_device *dev)
        iowrite16(lp->mcr0, ioaddr + MCR0);
 
        /* Fill the MAC hash tables with their values */
-       if (lp->mcr0 && MCR0_HASH_EN) {
+       if (lp->mcr0 & MCR0_HASH_EN) {
                iowrite16(hash_table[0], ioaddr + MAR0);
                iowrite16(hash_table[1], ioaddr + MAR1);
                iowrite16(hash_table[2], ioaddr + MAR2);
index 92b45f08858fab787a7ac3de3297f9b8c318ea67..6f06aa10f0d729a040a6e34a244d57338ba3025f 100644 (file)
@@ -1292,7 +1292,7 @@ static void __rtl8169_check_link_status(struct net_device *dev,
                netif_carrier_off(dev);
                netif_info(tp, ifdown, dev, "link down\n");
                if (pm)
-                       pm_schedule_suspend(&tp->pci_dev->dev, 100);
+                       pm_schedule_suspend(&tp->pci_dev->dev, 5000);
        }
        spin_unlock_irqrestore(&tp->lock, flags);
 }
index d2be42aafbef201e48ea5d1fb177564aaeaacf31..8843071fe987bd1543b91387f6da9c3c9a8d0800 100644 (file)
@@ -1937,6 +1937,7 @@ static int __devinit smsc911x_init(struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
        unsigned int byte_test;
+       unsigned int to = 100;
 
        SMSC_TRACE(pdata, probe, "Driver Parameters:");
        SMSC_TRACE(pdata, probe, "LAN base: 0x%08lX",
@@ -1952,6 +1953,17 @@ static int __devinit smsc911x_init(struct net_device *dev)
                return -ENODEV;
        }
 
+       /*
+        * poll the READY bit in PMT_CTRL. Any other access to the device is
+        * forbidden while this bit isn't set. Try for 100ms
+        */
+       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+               udelay(1000);
+       if (to == 0) {
+               pr_err("Device not READY in 100ms aborting\n");
+               return -ENODEV;
+       }
+
        /* Check byte ordering */
        byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
        SMSC_TRACE(pdata, probe, "BYTE_TEST: 0x%08X", byte_test);
index da66ac511c4c60df8dabe849cd02ba9ae2d76dad..4d5402a1d262976bdede2fed63875000d81e17fb 100644 (file)
@@ -39,10 +39,11 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
        /* DMA SW reset */
        value |= DMA_BUS_MODE_SFT_RESET;
        writel(value, ioaddr + DMA_BUS_MODE);
-       limit = 15000;
+       limit = 10;
        while (limit--) {
                if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
                        break;
+               mdelay(10);
        }
        if (limit < 0)
                return -EBUSY;
index 627f656b0f3c581bbb20a45084b7c1fd87a22194..bc17fd08b55dc9085a9ea66cefe1f388fd3ce985 100644 (file)
@@ -41,10 +41,11 @@ static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
        /* DMA SW reset */
        value |= DMA_BUS_MODE_SFT_RESET;
        writel(value, ioaddr + DMA_BUS_MODE);
-       limit = 15000;
+       limit = 10;
        while (limit--) {
                if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
                        break;
+               mdelay(10);
        }
        if (limit < 0)
                return -EBUSY;
index 9bafa6cf9e8b5af13b262e1efc28809ff9a9c910..a140a8fbf0515c70e2471639907239f34b55f036 100644 (file)
@@ -72,7 +72,6 @@ struct stmmac_priv {
        spinlock_t lock;
        spinlock_t tx_lock;
        int wolopts;
-       int wolenabled;
        int wol_irq;
 #ifdef CONFIG_STMMAC_TIMER
        struct stmmac_timer *tm;
@@ -80,6 +79,7 @@ struct stmmac_priv {
        struct plat_stmmacenet_data *plat;
        struct stmmac_counters mmc;
        struct dma_features dma_cap;
+       int hw_cap_support;
 };
 
 extern int stmmac_mdio_unregister(struct net_device *ndev);
index e8eff09bbbd73c7b036f5cd9520d030c949fddc1..0395f9eba801e9281f6af9a9fca8dc12057b55e4 100644 (file)
@@ -430,6 +430,12 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        struct stmmac_priv *priv = netdev_priv(dev);
        u32 support = WAKE_MAGIC | WAKE_UCAST;
 
+       /* By default almost all GMAC devices support the WoL via
+        * magic frame but we can disable it if the HW capability
+        * register shows no support for pmt_magic_frame. */
+       if ((priv->hw_cap_support) && (!priv->dma_cap.pmt_magic_frame))
+               wol->wolopts &= ~WAKE_MAGIC;
+
        if (!device_can_wakeup(priv->device))
                return -EINVAL;
 
index 20546bbbb8db04744d39b2e4a4e5710f04fa6538..8ea770a89f2556b8c762f2af345e5044d45ff9ba 100644 (file)
@@ -321,12 +321,10 @@ static int stmmac_init_phy(struct net_device *dev)
        }
 
        /* Stop Advertising 1000BASE Capability if interface is not GMII */
-       if ((interface) && ((interface == PHY_INTERFACE_MODE_MII) ||
-           (interface == PHY_INTERFACE_MODE_RMII))) {
-               phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
-                                     SUPPORTED_Asym_Pause);
-               phydev->advertising = phydev->supported;
-       }
+       if ((interface == PHY_INTERFACE_MODE_MII) ||
+           (interface == PHY_INTERFACE_MODE_RMII))
+               phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
+                                        SUPPORTED_1000baseT_Full);
 
        /*
         * Broken HW is sometimes missing the pull-up resistor on the
@@ -807,8 +805,29 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
        return 0;
 }
 
-/* New GMAC chips support a new register to indicate the
- * presence of the optional feature/functions.
+/**
+ * stmmac_selec_desc_mode
+ * @dev : device pointer
+ * Description: select the Enhanced/Alternate or Normal descriptors */
+static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
+{
+       if (priv->plat->enh_desc) {
+               pr_info(" Enhanced/Alternate descriptors\n");
+               priv->hw->desc = &enh_desc_ops;
+       } else {
+               pr_info(" Normal descriptors\n");
+               priv->hw->desc = &ndesc_ops;
+       }
+}
+
+/**
+ * stmmac_get_hw_features
+ * @priv : private device pointer
+ * Description:
+ *  new GMAC chip generations have a new register to indicate the
+ *  presence of the optional feature/functions.
+ *  This can be also used to override the value passed through the
+ *  platform and necessary for old MAC10/100 and GMAC chips.
  */
 static int stmmac_get_hw_features(struct stmmac_priv *priv)
 {
@@ -829,7 +848,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
                        (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
                priv->dma_cap.pmt_magic_frame =
                        (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
-               /*MMC*/
+               /* MMC */
                priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
                /* IEEE 1588-2002*/
                priv->dma_cap.time_stamp =
@@ -857,8 +876,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
                priv->dma_cap.enh_desc =
                        (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
 
-       } else
-               pr_debug("\tNo HW DMA feature register supported");
+       }
 
        return hw_cap;
 }
@@ -913,6 +931,44 @@ static int stmmac_open(struct net_device *dev)
                goto open_error;
        }
 
+       stmmac_get_synopsys_id(priv);
+
+       priv->hw_cap_support = stmmac_get_hw_features(priv);
+
+       if (priv->hw_cap_support) {
+               pr_info(" Support DMA HW capability register");
+
+               /* We can override some gmac/dma configuration fields: e.g.
+                * enh_desc, tx_coe (e.g. that are passed through the
+                * platform) with the values from the HW capability
+                * register (if supported).
+                */
+               priv->plat->enh_desc = priv->dma_cap.enh_desc;
+               priv->plat->tx_coe = priv->dma_cap.tx_coe;
+               priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
+
+               /* By default disable wol on magic frame if not supported */
+               if (!priv->dma_cap.pmt_magic_frame)
+                       priv->wolopts &= ~WAKE_MAGIC;
+
+       } else
+               pr_info(" No HW DMA feature register supported");
+
+       /* Select the enhnaced/normal descriptor structures */
+       stmmac_selec_desc_mode(priv);
+
+       /* PMT module is not integrated in all the MAC devices. */
+       if (priv->plat->pmt) {
+               pr_info(" Remote wake-up capable\n");
+               device_set_wakeup_capable(priv->device, 1);
+       }
+
+       priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
+       if (priv->rx_coe)
+               pr_info(" Checksum Offload Engine supported\n");
+       if (priv->plat->tx_coe)
+               pr_info(" Checksum insertion supported\n");
+
        /* Create and initialize the TX/RX descriptors chains. */
        priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
        priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
@@ -935,15 +991,6 @@ static int stmmac_open(struct net_device *dev)
        /* Initialize the MAC Core */
        priv->hw->mac->core_init(priv->ioaddr);
 
-       stmmac_get_synopsys_id(priv);
-
-       stmmac_get_hw_features(priv);
-
-       priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
-       if (priv->rx_coe)
-               pr_info("stmmac: Rx Checksum Offload Engine supported\n");
-       if (priv->plat->tx_coe)
-               pr_info("\tTX Checksum insertion supported\n");
        netdev_update_features(dev);
 
        /* Request the IRQ lines */
@@ -1489,9 +1536,7 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        if (!priv->phydev)
                return -EINVAL;
 
-       spin_lock(&priv->lock);
        ret = phy_mii_ioctl(priv->phydev, rq, cmd);
-       spin_unlock(&priv->lock);
 
        return ret;
 }
@@ -1558,7 +1603,7 @@ static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
        struct net_device *dev = seq->private;
        struct stmmac_priv *priv = netdev_priv(dev);
 
-       if (!stmmac_get_hw_features(priv)) {
+       if (!priv->hw_cap_support) {
                seq_printf(seq, "DMA HW features not supported\n");
                return 0;
        }
@@ -1766,12 +1811,6 @@ static int stmmac_mac_device_setup(struct net_device *dev)
        if (!device)
                return -ENOMEM;
 
-       if (priv->plat->enh_desc) {
-               device->desc = &enh_desc_ops;
-               pr_info("\tEnhanced descriptor structure\n");
-       } else
-               device->desc = &ndesc_ops;
-
        priv->hw = device;
        priv->hw->ring = &ring_mode_ops;
 
@@ -1845,11 +1884,6 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
 
        priv->ioaddr = addr;
 
-       /* PMT module is not integrated in all the MAC devices. */
-       if (plat_dat->pmt) {
-               pr_info("\tPMT module supported\n");
-               device_set_wakeup_capable(&pdev->dev, 1);
-       }
        /*
         * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
         * The external wake up irq can be passed through the platform code
@@ -1862,7 +1896,6 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
        if (priv->wol_irq == -ENXIO)
                priv->wol_irq = ndev->irq;
 
-
        platform_set_drvdata(pdev, ndev);
 
        /* Set the I/O base addr */
@@ -1875,7 +1908,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
                        goto out_free_ndev;
        }
 
-       /* MAC HW revice detection */
+       /* MAC HW device detection */
        ret = stmmac_mac_device_setup(ndev);
        if (ret < 0)
                goto out_plat_exit;
@@ -1978,12 +2011,13 @@ static int stmmac_suspend(struct device *dev)
        if (!ndev || !netif_running(ndev))
                return 0;
 
+       if (priv->phydev)
+               phy_stop(priv->phydev);
+
        spin_lock(&priv->lock);
 
        netif_device_detach(ndev);
        netif_stop_queue(ndev);
-       if (priv->phydev)
-               phy_stop(priv->phydev);
 
 #ifdef CONFIG_STMMAC_TIMER
        priv->tm->timer_stop();
@@ -2041,12 +2075,13 @@ static int stmmac_resume(struct device *dev)
 #endif
        napi_enable(&priv->napi);
 
-       if (priv->phydev)
-               phy_start(priv->phydev);
-
        netif_start_queue(ndev);
 
        spin_unlock(&priv->lock);
+
+       if (priv->phydev)
+               phy_start(priv->phydev);
+
        return 0;
 }
 
index c517dac02ae1837343ff48465274f7b3e54caae3..cf14ab9db5768f7781f7b9983120c01644fad0aa 100644 (file)
@@ -2637,7 +2637,7 @@ static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int i
        sbus_dp = op->dev.parent->of_node;
 
        /* We can match PCI devices too, do not accept those here. */
-       if (strcmp(sbus_dp->name, "sbus"))
+       if (strcmp(sbus_dp->name, "sbus") && strcmp(sbus_dp->name, "sbi"))
                return err;
 
        if (is_qfe) {
index caf3659e173cda3a04735cb1ecad7cfd94de27c7..2681b53820eefaf3edaa8e6e336b9b6de12d8bf0 100644 (file)
@@ -114,6 +114,7 @@ void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
                return;
        temac_iow(lp, XTE_LSW0_OFFSET, value);
        temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
+       temac_indirect_busywait(lp);
 }
 
 /**
@@ -203,6 +204,9 @@ static void temac_dma_bd_release(struct net_device *ndev)
        struct temac_local *lp = netdev_priv(ndev);
        int i;
 
+       /* Reset Local Link (DMA) */
+       lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
+
        for (i = 0; i < RX_BD_NUM; i++) {
                if (!lp->rx_skb[i])
                        break;
@@ -860,6 +864,8 @@ static int temac_open(struct net_device *ndev)
                phy_start(lp->phy_dev);
        }
 
+       temac_device_reset(ndev);
+
        rc = request_irq(lp->tx_irq, ll_temac_tx_irq, 0, ndev->name, ndev);
        if (rc)
                goto err_tx_irq;
@@ -867,7 +873,6 @@ static int temac_open(struct net_device *ndev)
        if (rc)
                goto err_rx_irq;
 
-       temac_device_reset(ndev);
        return 0;
 
  err_rx_irq:
index 7393eb732ee6737b31fa28c70f5baf1c4e1f3499..95eb34fdbba7b2ac1996303675bc9b0b262cbadf 100644 (file)
@@ -36,4 +36,4 @@ config ROADRUNNER_LARGE_RINGS
          kernel code or by user space programs. Say Y here only if you have
          the memory.
 
-endif /* HIPPI */
+endif # HIPPI
index a3ce3d4561eda101d9f54168d03d383b991aeac3..74134970b7095c4faae3f9f627358bd69617353d 100644 (file)
@@ -192,6 +192,13 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
                         */
                        macvlan_broadcast(skb, port, src->dev,
                                          MACVLAN_MODE_VEPA);
+               else {
+                       /* forward to original port. */
+                       vlan = src;
+                       ret = macvlan_broadcast_one(skb, vlan, eth, 0);
+                       goto out;
+               }
+
                return RX_HANDLER_PASS;
        }
 
index e81e22e3d1d2fcf84be504403002b52d492a01d8..e6fed4d4cb77f70c8c6d62af16d53a57ed31c99c 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/usb/usbnet.h>
 #include <linux/slab.h>
 
-#define DRIVER_VERSION "26-Sep-2011"
+#define DRIVER_VERSION "08-Nov-2011"
 #define DRIVER_NAME "asix"
 
 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
 #define MARVELL_CTRL_TXDELAY   0x0002
 #define MARVELL_CTRL_RXDELAY   0x0080
 
-#define        PHY_MODE_RTL8211CL      0x0004
+#define        PHY_MODE_RTL8211CL      0x000C
 
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct asix_data {
@@ -652,9 +652,17 @@ static u32 asix_get_phyid(struct usbnet *dev)
 {
        int phy_reg;
        u32 phy_id;
+       int i;
 
-       phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
-       if (phy_reg < 0)
+       /* Poll for the rare case the FW or phy isn't ready yet.  */
+       for (i = 0; i < 100; i++) {
+               phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
+               if (phy_reg != 0 && phy_reg != 0xFFFF)
+                       break;
+               mdelay(1);
+       }
+
+       if (phy_reg <= 0 || phy_reg == 0xFFFF)
                return 0;
 
        phy_id = (phy_reg & 0xffff) << 16;
@@ -1075,7 +1083,7 @@ static const struct net_device_ops ax88772_netdev_ops = {
 
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-       int ret;
+       int ret, embd_phy;
        struct asix_data *data = (struct asix_data *)&dev->data;
        u8 buf[ETH_ALEN];
        u32 phyid;
@@ -1100,16 +1108,36 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->mii.reg_num_mask = 0x1f;
        dev->mii.phy_id = asix_get_phy_addr(dev);
 
-       phyid = asix_get_phyid(dev);
-       dbg("PHYID=0x%08x", phyid);
-
        dev->net->netdev_ops = &ax88772_netdev_ops;
        dev->net->ethtool_ops = &ax88772_ethtool_ops;
 
-       ret = ax88772_reset(dev);
+       embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
+
+       /* Reset the PHY to normal operation mode */
+       ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
+       if (ret < 0) {
+               dbg("Select PHY #1 failed: %d", ret);
+               return ret;
+       }
+
+       ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL);
+       if (ret < 0)
+               return ret;
+
+       msleep(150);
+
+       ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
        if (ret < 0)
                return ret;
 
+       msleep(150);
+
+       ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE);
+
+       /* Read PHYID register *AFTER* the PHY was reset properly */
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
+
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
        if (dev->driver_info->flags & FLAG_FRAMING_AX) {
                /* hard_mtu  is still the default - the device does not support
@@ -1220,6 +1248,7 @@ static int ax88178_reset(struct usbnet *dev)
        __le16 eeprom;
        u8 status;
        int gpio0 = 0;
+       u32 phyid;
 
        asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status);
        dbg("GPIO Status: 0x%04x", status);
@@ -1235,12 +1264,13 @@ static int ax88178_reset(struct usbnet *dev)
                data->ledmode = 0;
                gpio0 = 1;
        } else {
-               data->phymode = le16_to_cpu(eeprom) & 7;
+               data->phymode = le16_to_cpu(eeprom) & 0x7F;
                data->ledmode = le16_to_cpu(eeprom) >> 8;
                gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1;
        }
        dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
 
+       /* Power up external GigaPHY through AX88178 GPIO pin */
        asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
        if ((le16_to_cpu(eeprom) >> 8) != 1) {
                asix_write_gpio(dev, 0x003c, 30);
@@ -1252,6 +1282,13 @@ static int ax88178_reset(struct usbnet *dev)
                asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
        }
 
+       /* Read PHYID register *AFTER* powering up PHY */
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
+
+       /* Set AX88178 to enable MII/GMII/RGMII interface for external PHY */
+       asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL);
+
        asix_sw_reset(dev, 0);
        msleep(150);
 
@@ -1396,7 +1433,6 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        int ret;
        u8 buf[ETH_ALEN];
-       u32 phyid;
        struct asix_data *data = (struct asix_data *)&dev->data;
 
        data->eeprom_len = AX88772_EEPROM_LEN;
@@ -1423,12 +1459,12 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->netdev_ops = &ax88178_netdev_ops;
        dev->net->ethtool_ops = &ax88178_ethtool_ops;
 
-       phyid = asix_get_phyid(dev);
-       dbg("PHYID=0x%08x", phyid);
+       /* Blink LEDS so users know driver saw dongle */
+       asix_sw_reset(dev, 0);
+       msleep(150);
 
-       ret = ax88178_reset(dev);
-       if (ret < 0)
-               return ret;
+       asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
+       msleep(150);
 
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
        if (dev->driver_info->flags & FLAG_FRAMING_AX) {
index c924ea2bce07a4c06aa8d6ab5d9c23620b446915..99ed6eb4dfaf6b8b1153dbe9bfcb4e5917500986 100644 (file)
@@ -567,7 +567,7 @@ static const struct usb_device_id   products [] = {
 {
        USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
-       .driver_info = (unsigned long)&wwan_info,
+       .driver_info = 0,
 },
 
 /*
index d43db32f94781f64e57fc4285c7c398e9287e885..9c26c6390d69a72abffbf47dc91d9aea96ec1ba0 100644 (file)
@@ -144,10 +144,11 @@ static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        }
 
        frame = (struct vl600_frame_hdr *) buf->data;
-       /* NOTE: Should check that frame->magic == 0x53544448?
-        * Otherwise if we receive garbage at the beginning of the frame
-        * we may end up allocating a huge buffer and saving all the
-        * future incoming data into it.  */
+       /* Yes, check that frame->magic == 0x53544448 (or 0x44544d48),
+        * otherwise we may run out of memory w/a bad packet */
+       if (ntohl(frame->magic) != 0x53544448 &&
+                       ntohl(frame->magic) != 0x44544d48)
+               goto error;
 
        if (buf->len < sizeof(*frame) ||
                        buf->len != le32_to_cpup(&frame->len)) {
@@ -296,6 +297,11 @@ encapsulate:
         * overwrite the remaining fields.
         */
        packet = (struct vl600_pkt_hdr *) skb->data;
+       /* The VL600 wants IPv6 packets to have an IPv4 ethertype
+        * Since this modem only supports IPv4 and IPv6, just set all
+        * frames to 0x0800 (ETH_P_IP)
+        */
+       packet->h_proto = htons(ETH_P_IP);
        memset(&packet->dummy, 0, sizeof(packet->dummy));
        packet->len = cpu_to_le32(orig_len);
 
@@ -308,21 +314,12 @@ encapsulate:
        if (skb->len < full_len) /* Pad */
                skb_put(skb, full_len - skb->len);
 
-       /* The VL600 wants IPv6 packets to have an IPv4 ethertype
-        * Check if this is an IPv6 packet, and set the ethertype
-        * to 0x800
-        */
-       if ((skb->data[sizeof(struct vl600_pkt_hdr *) + 0x22] & 0xf0) == 0x60) {
-               skb->data[sizeof(struct vl600_pkt_hdr *) + 0x20] = 0x08;
-               skb->data[sizeof(struct vl600_pkt_hdr *) + 0x21] = 0;
-       }
-
        return skb;
 }
 
 static const struct driver_info        vl600_info = {
        .description    = "LG VL600 modem",
-       .flags          = FLAG_ETHER | FLAG_RX_ASSEMBLE,
+       .flags          = FLAG_RX_ASSEMBLE | FLAG_WWAN,
        .bind           = vl600_bind,
        .unbind         = vl600_unbind,
        .status         = usbnet_cdc_status,
index 22a7cf951e728132b6f55d0d99584fc50e374eaa..a5b9b12ef268134fef1e978d8e19ce5468c16135 100644 (file)
@@ -51,6 +51,7 @@
 #define USB_VENDOR_ID_SMSC             (0x0424)
 #define USB_PRODUCT_ID_LAN7500         (0x7500)
 #define USB_PRODUCT_ID_LAN7505         (0x7505)
+#define RXW_PADDING                    2
 
 #define check_warn(ret, fmt, args...) \
        ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@ -1088,13 +1089,13 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
                memcpy(&rx_cmd_b, skb->data, sizeof(rx_cmd_b));
                le32_to_cpus(&rx_cmd_b);
-               skb_pull(skb, 4 + NET_IP_ALIGN);
+               skb_pull(skb, 4 + RXW_PADDING);
 
                packet = skb->data;
 
                /* get the packet length */
-               size = (rx_cmd_a & RX_CMD_A_LEN) - NET_IP_ALIGN;
-               align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
+               size = (rx_cmd_a & RX_CMD_A_LEN) - RXW_PADDING;
+               align_count = (4 - ((size + RXW_PADDING) % 4)) % 4;
 
                if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
                        netif_dbg(dev, rx_err, dev->net,
index 7d6082160bcc42377a51ba2b8be6f60a37eec093..fae0fbd8bc887a99ca0e068bbc4d06bed884775c 100644 (file)
@@ -1057,7 +1057,8 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
        unsigned long           flags;
        int retval;
 
-       skb_tx_timestamp(skb);
+       if (skb)
+               skb_tx_timestamp(skb);
 
        // some devices want funky USB-level framing, for
        // win32 driver (usually) and/or hardware quirks
index e0ab0657cc3a8808379ae0cc93e32e0863e13305..88279e325dcac0037ba3b6ed6b13a22bf23bc752 100644 (file)
@@ -868,10 +868,6 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
        /* Do PA Calibration */
        ar9002_hw_pa_cal(ah, true);
 
-       /* Do NF Calibration after DC offset and other calibrations */
-       ath9k_hw_loadnf(ah, chan);
-       ath9k_hw_start_nfcal(ah, true);
-
        if (ah->caldata)
                ah->caldata->nfcal_pending = true;
 
index 16851cb109a6302d492e6b4ce1a5f6f143d3433e..12a730dcb500912ad81bfeebfe6b8f9119cdfa33 100644 (file)
@@ -908,12 +908,15 @@ static bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
        int i;
        bool restore;
 
-       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT) || !ah->caldata)
+       if (!ah->caldata)
                return false;
 
        hist = &ah->caldata->rtt_hist;
+       if (!hist->num_readings)
+               return false;
+
        ar9003_hw_rtt_enable(ah);
-       ar9003_hw_rtt_set_mask(ah, 0x10);
+       ar9003_hw_rtt_set_mask(ah, 0x00);
        for (i = 0; i < AR9300_MAX_CHAINS; i++) {
                if (!(ah->rxchainmask & (1 << i)))
                        continue;
@@ -1070,6 +1073,7 @@ skip_tx_iqcal:
                if (is_reusable && (hist->num_readings < RTT_HIST_MAX)) {
                        u32 *table;
 
+                       hist->num_readings++;
                        for (i = 0; i < AR9300_MAX_CHAINS; i++) {
                                if (!(ah->rxchainmask & (1 << i)))
                                        continue;
@@ -1081,9 +1085,6 @@ skip_tx_iqcal:
                ar9003_hw_rtt_disable(ah);
        }
 
-       ath9k_hw_loadnf(ah, chan);
-       ath9k_hw_start_nfcal(ah, true);
-
        /* Initialize list pointers */
        ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
        ah->supp_cals = IQ_MISMATCH_CAL;
index 2f4023e660810c53aca60314d6668c7e3f857455..4114fe752c6b4f85485ef13024350dc6b9d55f8f 100644 (file)
 
 #define AR_PHY_TXGAIN_TABLE      (AR_SM_BASE + 0x300)
 
-#define AR_PHY_TX_IQCAL_CONTROL_0   (AR_SM_BASE + AR_SREV_9485(ah) ? \
-                                                0x3c4 : 0x444)
-#define AR_PHY_TX_IQCAL_CONTROL_1   (AR_SM_BASE + AR_SREV_9485(ah) ? \
-                                                0x3c8 : 0x448)
-#define AR_PHY_TX_IQCAL_START       (AR_SM_BASE + AR_SREV_9485(ah) ? \
-                                                0x3c4 : 0x440)
-#define AR_PHY_TX_IQCAL_STATUS_B0   (AR_SM_BASE + AR_SREV_9485(ah) ? \
-                                                0x3f0 : 0x48c)
+#define AR_PHY_TX_IQCAL_CONTROL_0   (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+                                                0x3c4 : 0x444))
+#define AR_PHY_TX_IQCAL_CONTROL_1   (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+                                                0x3c8 : 0x448))
+#define AR_PHY_TX_IQCAL_START       (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+                                                0x3c4 : 0x440))
+#define AR_PHY_TX_IQCAL_STATUS_B0   (AR_SM_BASE + (AR_SREV_9485(ah) ? \
+                                                0x3f0 : 0x48c))
 #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i)    (AR_SM_BASE + \
                                             (AR_SREV_9485(ah) ? \
                                              0x3d0 : 0x450) + ((_i) << 2))
 #define AR_SWITCH_TABLE_ALL_S (0)
 
 #define AR_PHY_65NM_CH0_THERM       (AR_SREV_9300(ah) ? 0x16290 :\
-                                       (AR_SREV_9485(ah) ? 0x1628c : 0x16294))
+                                       (AR_SREV_9462(ah) ? 0x16294 : 0x1628c))
 
 #define AR_PHY_65NM_CH0_THERM_LOCAL   0x80000000
 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
 #define AR_PHY_65NM_CH2_RXTX2       0x16904
 
 #define AR_CH0_TOP2            (AR_SREV_9300(ah) ? 0x1628c : \
-                                       (AR_SREV_9485(ah) ? 0x16284 : 0x16290))
+                                       (AR_SREV_9462(ah) ? 0x16290 : 0x16284))
 #define AR_CH0_TOP2_XPABIASLVL         0xf000
 #define AR_CH0_TOP2_XPABIASLVL_S       12
 
 #define AR_CH0_XTAL            (AR_SREV_9300(ah) ? 0x16294 : \
-                                       (AR_SREV_9485(ah) ? 0x16290 : 0x16298))
+                                       (AR_SREV_9462(ah) ? 0x16298 : 0x16290))
 #define AR_CH0_XTAL_CAPINDAC   0x7f000000
 #define AR_CH0_XTAL_CAPINDAC_S 24
 #define AR_CH0_XTAL_CAPOUTDAC  0x00fe0000
 #define AR_PHY_TPC_5_B1         (AR_SM1_BASE + 0x208)
 #define AR_PHY_TPC_6_B1         (AR_SM1_BASE + 0x20c)
 #define AR_PHY_TPC_11_B1        (AR_SM1_BASE + 0x220)
-#define AR_PHY_PDADC_TAB_1     (AR_SM1_BASE + (AR_SREV_AR9300(ah) ? \
-                                       0x240 : 0x280))
+#define AR_PHY_PDADC_TAB_1     (AR_SM1_BASE + (AR_SREV_AR9462(ah) ? \
+                                       0x280 : 0x240))
 #define AR_PHY_TPC_19_B1       (AR_SM1_BASE + 0x240)
 #define AR_PHY_TPC_19_B1_ALPHA_THERM           0xff
 #define AR_PHY_TPC_19_B1_ALPHA_THERM_S         0
 #define AR_PHY_AIC_SRAM_ADDR_B1        (AR_SM1_BASE + 0x5f0)
 #define AR_PHY_AIC_SRAM_DATA_B1        (AR_SM1_BASE + 0x5f4)
 
-#define AR_PHY_RTT_TABLE_SW_INTF_B(i)  (0x384 + (i) ? \
-                                       AR_SM1_BASE : AR_SM_BASE)
-#define AR_PHY_RTT_TABLE_SW_INTF_1_B(i)        (0x388 + (i) ? \
-                                       AR_SM1_BASE : AR_SM_BASE)
+#define AR_PHY_RTT_TABLE_SW_INTF_B(i)  (0x384 + ((i) ? \
+                                       AR_SM1_BASE : AR_SM_BASE))
+#define AR_PHY_RTT_TABLE_SW_INTF_1_B(i)        (0x388 + ((i) ? \
+                                       AR_SM1_BASE : AR_SM_BASE))
 /*
  * Channel 2 Register Map
  */
index 611ea6ce8508dfb760a1172ea46793e6716c48e3..d16d029f81a9db1d45dbd7f0115e057d3be3bf1d 100644 (file)
@@ -521,7 +521,7 @@ static const u32 ar9485_1_1_radio_postamble[][2] = {
        {0x000160ac, 0x24611800},
        {0x000160b0, 0x03284f3e},
        {0x0001610c, 0x00170000},
-       {0x00016140, 0x10804008},
+       {0x00016140, 0x50804008},
 };
 
 static const u32 ar9485_1_1_mac_postamble[][5] = {
@@ -603,7 +603,7 @@ static const u32 ar9485_1_1_radio_core[][2] = {
 
 static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
        /* Addr        allmodes */
-       {0x00018c00, 0x10052e5e},
+       {0x00018c00, 0x18052e5e},
        {0x00018c04, 0x000801d8},
        {0x00018c08, 0x0000080c},
 };
@@ -776,7 +776,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
 
 static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
        /* Addr        allmodes */
-       {0x00018c00, 0x10013e5e},
+       {0x00018c00, 0x18013e5e},
        {0x00018c04, 0x000801d8},
        {0x00018c08, 0x0000080c},
 };
@@ -882,7 +882,7 @@ static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
 
 static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
        /* Addr        allmodes  */
-       {0x00018c00, 0x10012e5e},
+       {0x00018c00, 0x18012e5e},
        {0x00018c04, 0x000801d8},
        {0x00018c08, 0x0000080c},
 };
@@ -1021,7 +1021,7 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
 
 static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = {
        /* Addr        allmodes */
-       {0x00018c00, 0x10053e5e},
+       {0x00018c00, 0x18053e5e},
        {0x00018c04, 0x000801d8},
        {0x00018c08, 0x0000080c},
 };
index 4952ad8c4e8cb2f4f14c685d85aebbdf33fb233c..8873c6e6fb9627c02c41d4b1d36ffb340da3eacf 100644 (file)
@@ -1725,6 +1725,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        if (!ath9k_hw_init_cal(ah, chan))
                return -EIO;
 
+       ath9k_hw_loadnf(ah, chan);
+       ath9k_hw_start_nfcal(ah, true);
+
        ENABLE_REGWRITE_BUFFER(ah);
 
        ath9k_hw_restore_chainmask(ah);
@@ -1824,7 +1827,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
        }
 
        /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
-       REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
 }
 
 /*
index d20946939cd8cae0968abfb096dbe3321c0e63eb..59472e1605cd89779e06c299937ba950968b3daf 100644 (file)
@@ -296,7 +296,8 @@ static void carl9170_tx_release(struct kref *ref)
                        super = (void *)skb->data;
                        txinfo->status.ampdu_len = super->s.rix;
                        txinfo->status.ampdu_ack_len = super->s.cnt;
-               } else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
+               } else if ((txinfo->flags & IEEE80211_TX_STAT_ACK) &&
+                          !(txinfo->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
                        /*
                         * drop redundant tx_status reports:
                         *
@@ -308,15 +309,17 @@ static void carl9170_tx_release(struct kref *ref)
                         *
                         * 3. minstrel_ht is picky, it only accepts
                         *    reports of frames with the TX_STATUS_AMPDU flag.
+                        *
+                        * 4. mac80211 is not particularly interested in
+                        *    feedback either [CTL_REQ_TX_STATUS not set]
                         */
 
                        dev_kfree_skb_any(skb);
                        return;
                } else {
                        /*
-                        * Frame has failed, but we want to keep it in
-                        * case it was lost due to a power-state
-                        * transition.
+                        * Either the frame transmission has failed or
+                        * mac80211 requested tx status.
                         */
                }
        }
index 85fa9cc73502c8f30b70a8d15da73dd28071fdcf..65ecb5bab25a2a0a0c1e64d5122397238ab1e0ca 100644 (file)
@@ -254,6 +254,8 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
        int r;
 
        sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+       if (!sband)
+               return;
 
        /*
         * If no country IE has been received always enable active scan
index c73e8600d218673b28838e898bba1d903a6c493b..5f77cbe0b6aaeb5d6e121ad5e37b70a3b8596d62 100644 (file)
@@ -175,6 +175,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
        }
 }
 
+/* TODO: verify if needed for SSLPN or LCN  */
 static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
 {
        const struct b43_phy *phy = &dev->phy;
@@ -256,6 +257,9 @@ int b43_generate_txhdr(struct b43_wldev *dev,
        unsigned int plcp_fragment_len;
        u32 mac_ctl = 0;
        u16 phy_ctl = 0;
+       bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP ||
+                             phy->type == B43_PHYTYPE_N ||
+                             phy->type == B43_PHYTYPE_HT);
        u8 extra_ft = 0;
        struct ieee80211_rate *txrate;
        struct ieee80211_tx_rate *rates;
@@ -531,7 +535,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
                        extra_ft |= B43_TXH_EFT_RTSFB_CCK;
 
                if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
-                   phy->type == B43_PHYTYPE_N) {
+                   fill_phy_ctl1) {
                        txhdr->phy_ctl1_rts = cpu_to_le16(
                                b43_generate_tx_phy_ctl1(dev, rts_rate));
                        txhdr->phy_ctl1_rts_fb = cpu_to_le16(
@@ -552,7 +556,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
                break;
        }
 
-       if (phy->type == B43_PHYTYPE_N) {
+       if (fill_phy_ctl1) {
                txhdr->phy_ctl1 =
                        cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
                txhdr->phy_ctl1_fb =
@@ -736,7 +740,14 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 
        /* Link quality statistics */
        switch (chanstat & B43_RX_CHAN_PHYTYPE) {
+       case B43_PHYTYPE_HT:
+               /* TODO: is max the right choice? */
+               status.signal = max_t(__s8,
+                       max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1),
+                       rxhdr->phy_ht_power2);
+               break;
        case B43_PHYTYPE_N:
+               /* Broadcom has code for min and avg, but always uses max */
                if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
                        status.signal = max(rxhdr->power1, rxhdr->power2);
                else
@@ -827,7 +838,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 #endif
        return;
 drop:
-       b43dbg(dev->wl, "RX: Packet dropped\n");
        dev_kfree_skb_any(skb);
 }
 
index 16c514d54afabb6be6f57c078e631e5a7d4c8647..98d90747836a482fa836f6e30c8fc173e1c935e5 100644 (file)
@@ -249,6 +249,12 @@ struct b43_rxhdr_fw4 {
                } __packed;
        } __packed;
        union {
+               /* HT-PHY */
+               struct {
+                       PAD_BYTES(1);
+                       __s8 phy_ht_power0;
+               } __packed;
+
                /* RSSI for N-PHYs */
                struct {
                        __s8 power2;
@@ -257,7 +263,15 @@ struct b43_rxhdr_fw4 {
 
                __le16 phy_status2;     /* PHY RX Status 2 */
        } __packed;
-       __le16 phy_status3;     /* PHY RX Status 3 */
+       union {
+               /* HT-PHY */
+               struct {
+                       __s8 phy_ht_power1;
+                       __s8 phy_ht_power2;
+               } __packed;
+
+               __le16 phy_status3;     /* PHY RX Status 3 */
+       } __packed;
        union {
                /* Tested with 598.314, 644.1001 and 666.2 */
                struct {
index b56a30297c269712840a8696f77d1d84daab358a..6ebec8f42846977439c07844cba9a6f7e429801c 100644 (file)
@@ -358,13 +358,14 @@ static uint nrxdactive(struct dma_info *di, uint h, uint t)
 
 static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
 {
-       uint dmactrlflags = di->dma.dmactrlflags;
+       uint dmactrlflags;
 
        if (di == NULL) {
-               DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
+               DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n"));
                return 0;
        }
 
+       dmactrlflags = di->dma.dmactrlflags;
        dmactrlflags &= ~mask;
        dmactrlflags |= flags;
 
index b247a56d51354775b5cbc4cd16c54ee05d6deedf..001fdf140abbb72de6d12fe95dac3d8211158ff0 100644 (file)
@@ -1755,16 +1755,6 @@ static inline int iwl_check_stuck_queue(struct iwl_priv *priv, int txq)
 {
        if (iwl_trans_check_stuck_queue(trans(priv), txq)) {
                int ret;
-               if (txq == priv->shrd->cmd_queue) {
-                       /*
-                        * validate command queue still working
-                        * by sending "ECHO" command
-                        */
-                       if (!iwl_cmd_echo_test(priv))
-                               return 0;
-                       else
-                               IWL_DEBUG_HC(priv, "echo testing fail\n");
-               }
                ret = iwl_force_reset(priv, IWL_FW_RESET, false);
                return (ret == -EAGAIN) ? 0 : 1;
        }
index f0c623ade3fff149a21dedb3ff11a7bfb3caf464..1800029911adfa1e21dfc8d3c6b0d59614daf88f 100644 (file)
@@ -446,10 +446,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
 
        err = pci_enable_msi(pdev);
-       if (err) {
-               dev_printk(KERN_ERR, &pdev->dev, "pci_enable_msi failed");
-               goto out_iounmap;
-       }
+       if (err)
+               dev_printk(KERN_ERR, &pdev->dev,
+                       "pci_enable_msi failed(0X%x)", err);
 
        /* TODO: Move this away, not needed if not MSI */
        /* enable rfkill interrupt: hw bug w/a */
@@ -470,7 +469,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 out_disable_msi:
        pci_disable_msi(pdev);
-out_iounmap:
        pci_iounmap(pdev, pci_bus->hw_base);
 out_pci_release_regions:
        pci_set_drvdata(pdev, NULL);
index 8e8c75c997eef2e4ca576189e1fd265a7a3ac0bd..ce918980e97799a51fc3b0b9a732d28fe706c84a 100644 (file)
@@ -407,6 +407,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
        struct iwl_queue *q = &txq->q;
        enum dma_data_direction dma_dir;
        unsigned long flags;
+       spinlock_t *lock;
 
        if (!q->n_bd)
                return;
@@ -414,19 +415,22 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
        /* In the command queue, all the TBs are mapped as BIDI
         * so unmap them as such.
         */
-       if (txq_id == trans->shrd->cmd_queue)
+       if (txq_id == trans->shrd->cmd_queue) {
                dma_dir = DMA_BIDIRECTIONAL;
-       else
+               lock = &trans->hcmd_lock;
+       } else {
                dma_dir = DMA_TO_DEVICE;
+               lock = &trans->shrd->sta_lock;
+       }
 
-       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
+       spin_lock_irqsave(lock, flags);
        while (q->write_ptr != q->read_ptr) {
                /* The read_ptr needs to bound by q->n_window */
                iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr),
                                    dma_dir);
                q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
        }
-       spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+       spin_unlock_irqrestore(lock, flags);
 }
 
 /**
@@ -986,29 +990,16 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
        return 0;
 }
 
-static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans)
+static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 {
        unsigned long flags;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
+       /* tell the device to stop sending interrupts */
        spin_lock_irqsave(&trans->shrd->lock, flags);
        iwl_disable_interrupts(trans);
        spin_unlock_irqrestore(&trans->shrd->lock, flags);
 
-       /* wait to make sure we flush pending tasklet*/
-       synchronize_irq(bus(trans)->irq);
-       tasklet_kill(&trans_pcie->irq_tasklet);
-}
-
-static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
-{
-       /* stop and reset the on-board processor */
-       iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-       /* tell the device to stop sending interrupts */
-       iwl_trans_pcie_disable_sync_irq(trans);
-
        /* device going down, Stop using ICT table */
        iwl_disable_ict(trans);
 
@@ -1035,6 +1026,20 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 
        /* Stop the device, and put it in low power state */
        iwl_apm_stop(priv(trans));
+
+       /* Upon stop, the APM issues an interrupt if HW RF kill is set.
+        * Clean again the interrupt here
+        */
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+       iwl_disable_interrupts(trans);
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       /* wait to make sure we flush pending tasklet*/
+       synchronize_irq(bus(trans)->irq);
+       tasklet_kill(&trans_pcie->irq_tasklet);
+
+       /* stop and reset the on-board processor */
+       iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 }
 
 static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
index ff6378276ff08d5f06f29ac604304466aff37aac..a7f1ab28940d3ae6ad8e4fbda26b18087b4c21b4 100644 (file)
@@ -634,7 +634,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
                        if (channel &&
                            !(channel->flags & IEEE80211_CHAN_DISABLED))
                                cfg80211_inform_bss(wiphy, channel,
-                                       bssid, le64_to_cpu(*(__le64 *)tsfdesc),
+                                       bssid, get_unaligned_le64(tsfdesc),
                                        capa, intvl, ie, ielen,
                                        LBS_SCAN_RSSI_TO_MBM(rssi),
                                        GFP_KERNEL);
@@ -728,15 +728,9 @@ static void lbs_scan_worker(struct work_struct *work)
                le16_to_cpu(scan_cmd->hdr.size),
                lbs_ret_scan, 0);
 
-       if (priv->scan_channel >= priv->scan_req->n_channels) {
+       if (priv->scan_channel >= priv->scan_req->n_channels)
                /* Mark scan done */
-               if (priv->internal_scan)
-                       kfree(priv->scan_req);
-               else
-                       cfg80211_scan_done(priv->scan_req, false);
-
-               priv->scan_req = NULL;
-       }
+               lbs_scan_done(priv);
 
        /* Restart network */
        if (carrier)
@@ -774,6 +768,21 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal,
        lbs_deb_leave(LBS_DEB_CFG80211);
 }
 
+/*
+ * Clean up priv->scan_req.  Should be used to handle the allocation details.
+ */
+void lbs_scan_done(struct lbs_private *priv)
+{
+       WARN_ON(!priv->scan_req);
+
+       if (priv->internal_scan)
+               kfree(priv->scan_req);
+       else
+               cfg80211_scan_done(priv->scan_req, false);
+
+       priv->scan_req = NULL;
+}
+
 static int lbs_cfg_scan(struct wiphy *wiphy,
        struct net_device *dev,
        struct cfg80211_scan_request *request)
index a02ee151710e36a1f401912a7f1873ee09f9af37..558168ce634d519d67201d92c1992163550f4b4b 100644 (file)
@@ -16,6 +16,7 @@ int lbs_reg_notifier(struct wiphy *wiphy,
 void lbs_send_disconnect_notification(struct lbs_private *priv);
 void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
 
+void lbs_scan_done(struct lbs_private *priv);
 void lbs_scan_deinit(struct lbs_private *priv);
 int lbs_disconnect(struct lbs_private *priv, u16 reason);
 
index 11b69b300dc0821e52980fef3d248a50377f026a..728baa445259c5ead043fa2540017c6d9ee19135 100644 (file)
@@ -995,6 +995,7 @@ static int if_spi_host_to_card(struct lbs_private *priv,
                spin_unlock_irqrestore(&card->buffer_lock, flags);
                break;
        default:
+               kfree(packet);
                netdev_err(priv->dev, "can't transfer buffer of type %d\n",
                           type);
                err = -EINVAL;
index 4ae99a40dbf7f6aadb4ef9bbb8971237d5584cfe..957681dede1776b1a9ee94ab87626bb9e0f9ee63 100644 (file)
@@ -255,10 +255,8 @@ static int lbs_eth_stop(struct net_device *dev)
 
        lbs_update_mcast(priv);
        cancel_delayed_work_sync(&priv->scan_work);
-       if (priv->scan_req) {
-               cfg80211_scan_done(priv->scan_req, false);
-               priv->scan_req = NULL;
-       }
+       if (priv->scan_req)
+               lbs_scan_done(priv);
 
        netif_carrier_off(priv->dev);
 
index dae8dbb24a03e83352742b20c3320c9819019889..8d3ab378662b77ac4c55c40bceba1b8a53715552 100644 (file)
@@ -819,8 +819,10 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
                        wildcard_ssid_tlv->header.len = cpu_to_le16(
                                (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
                                                         max_ssid_length)));
-                       wildcard_ssid_tlv->max_ssid_length =
-                               user_scan_in->ssid_list[ssid_idx].max_len;
+
+                       /* max_ssid_length = 0 tells firmware to perform
+                          specific scan for the SSID filled */
+                       wildcard_ssid_tlv->max_ssid_length = 0;
 
                        memcpy(wildcard_ssid_tlv->ssid,
                               user_scan_in->ssid_list[ssid_idx].ssid,
@@ -1469,7 +1471,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
                               s32 rssi, const u8 *ie_buf, size_t ie_len,
                               u16 beacon_period, u16 cap_info_bitmap, u8 band)
 {
-       struct mwifiex_bssdescriptor *bss_desc = NULL;
+       struct mwifiex_bssdescriptor *bss_desc;
        int ret;
        unsigned long flags;
        u8 *beacon_ie;
@@ -1484,6 +1486,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
 
        beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL);
        if (!beacon_ie) {
+               kfree(bss_desc);
                dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
                return -ENOMEM;
        }
index f1565792f2701c6285b202456c831341f6f5e181..377876315b8d4a9bcdcc91b228b14bed45bef943 100644 (file)
@@ -919,6 +919,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x050d, 0x935b) },
        /* Buffalo */
        { USB_DEVICE(0x0411, 0x00e8) },
+       { USB_DEVICE(0x0411, 0x0158) },
        { USB_DEVICE(0x0411, 0x016f) },
        { USB_DEVICE(0x0411, 0x01a2) },
        /* Corega */
index 2ec5c00235e612941fca457a20a9f16b1b8718b9..99ff12d0c29dfce934719f304cd66511fc30d514 100644 (file)
@@ -943,6 +943,7 @@ struct rt2x00_dev {
         * Powersaving work
         */
        struct delayed_work autowakeup_work;
+       struct work_struct sleep_work;
 
        /*
         * Data queue arrays for RX, TX, Beacon and ATIM.
index e1fb2a8569be292d0f26f5347b0bfa828737bd39..edd317fa7c0aafb06658d06616cc74a5e73c0bd0 100644 (file)
@@ -465,6 +465,23 @@ static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
        return NULL;
 }
 
+static void rt2x00lib_sleep(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, sleep_work);
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Check again is powersaving is enabled, to prevent races from delayed
+        * work execution.
+        */
+       if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
+               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
+                                IEEE80211_CONF_CHANGE_PS);
+}
+
 static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
                                      struct sk_buff *skb,
                                      struct rxdone_entry_desc *rxdesc)
@@ -512,8 +529,7 @@ static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
        cam |= (tim_ie->bitmap_ctrl & 0x01);
 
        if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
-               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
-                                IEEE80211_CONF_CHANGE_PS);
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work);
 }
 
 static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
@@ -1141,6 +1157,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
 
        INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
        INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+       INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
 
        /*
         * Let the driver probe the device to detect the capabilities.
@@ -1197,6 +1214,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
         */
        cancel_work_sync(&rt2x00dev->intf_work);
        cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
+       cancel_work_sync(&rt2x00dev->sleep_work);
        if (rt2x00_is_usb(rt2x00dev)) {
                del_timer_sync(&rt2x00dev->txstatus_timer);
                cancel_work_sync(&rt2x00dev->rxdone_work);
index 128ccb79318c86c7e0a8bc4a65c61389b58e959f..fc29c671cf3b34db3fc695fbd70209720a3c52e8 100644 (file)
@@ -559,7 +559,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
                                                break;
                                        }
                                /* Fail if SSID isn't present in the filters */
-                               if (j == req->n_ssids) {
+                               if (j == cmd->n_ssids) {
                                        ret = -EINVAL;
                                        goto out_free;
                                }
index 6d3dd3988d0f2891e65514a2bac68b184409ac1d..19c0115092dd7a692c0d035063a3e83c111618a2 100644 (file)
@@ -60,27 +60,27 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
  */
 struct device_node *of_irq_find_parent(struct device_node *child)
 {
-       struct device_node *p, *c = child;
+       struct device_node *p;
        const __be32 *parp;
 
-       if (!of_node_get(c))
+       if (!of_node_get(child))
                return NULL;
 
        do {
-               parp = of_get_property(c, "interrupt-parent", NULL);
+               parp = of_get_property(child, "interrupt-parent", NULL);
                if (parp == NULL)
-                       p = of_get_parent(c);
+                       p = of_get_parent(child);
                else {
                        if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
                                p = of_node_get(of_irq_dflt_pic);
                        else
                                p = of_find_node_by_phandle(be32_to_cpup(parp));
                }
-               of_node_put(c);
-               c = p;
+               of_node_put(child);
+               child = p;
        } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
 
-       return (p == child) ? NULL : p;
+       return p;
 }
 
 /**
@@ -424,6 +424,8 @@ void __init of_irq_init(const struct of_device_id *matches)
 
                desc->dev = np;
                desc->interrupt_parent = of_irq_find_parent(np);
+               if (desc->interrupt_parent == np)
+                       desc->interrupt_parent = NULL;
                list_add_tail(&desc->list, &intc_desc_list);
        }
 
index b6f9749b4fa769638392610221b0751fba73eabb..f02b5235056d938ac2713c4534ff0bd3d89d7c8f 100644 (file)
@@ -76,6 +76,7 @@ config PCI_IOV
 
 config PCI_PRI
        bool "PCI PRI support"
+       depends on PCI
        select PCI_ATS
        help
          PRI is the PCI Page Request Interface. It allows PCI devices that are
index 596172b4ae955802a5778dd0c375b870b9a11909..fce1c54a0c8d8acf480c4b208ced89fb060ac95a 100644 (file)
@@ -459,8 +459,17 @@ static int add_bridge(acpi_handle handle)
 {
        acpi_status status;
        unsigned long long tmp;
+       struct acpi_pci_root *root;
        acpi_handle dummy_handle;
 
+       /*
+        * We shouldn't use this bridge if PCIe native hotplug control has been
+        * granted by the BIOS for it.
+        */
+       root = acpi_pci_find_root(handle);
+       if (root && (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
+               return -ENODEV;
+
        /* if the bridge doesn't have _STA, we assume it is always there */
        status = acpi_get_handle(handle, "_STA", &dummy_handle);
        if (ACPI_SUCCESS(status)) {
@@ -1376,13 +1385,23 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
 static acpi_status
 find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
+       struct acpi_pci_root *root;
        int *count = (int *)context;
 
-       if (acpi_is_root_bridge(handle)) {
-               acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-                               handle_hotplug_event_bridge, NULL);
-                       (*count)++;
-       }
+       if (!acpi_is_root_bridge(handle))
+               return AE_OK;
+
+       root = acpi_pci_find_root(handle);
+       if (!root)
+               return AE_OK;
+
+       if (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)
+               return AE_OK;
+
+       (*count)++;
+       acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                                   handle_hotplug_event_bridge, NULL);
+
        return AE_OK ;
 }
 
index 1e9c9aacc3a6c82363b39602c5f6bab1b4bbd30d..085dbb5fc168be33de77d0ced5c411c807ffc2ef 100644 (file)
@@ -213,9 +213,6 @@ static int board_added(struct slot *p_slot)
                goto err_exit;
        }
 
-       /* Wait for 1 second after checking link training status */
-       msleep(1000);
-
        /* Check for a power fault */
        if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
                ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
index 96dc4734e4affcc6c7f763a9853342678df8a7c6..7b1414810ae3e0e0a5ccbcd9bec0f21051cf95db 100644 (file)
@@ -280,6 +280,14 @@ int pciehp_check_link_status(struct controller *ctrl)
         else
                 msleep(1000);
 
+       /*
+        * Need to wait for 1000 ms after Data Link Layer Link Active
+        * (DLLLA) bit reads 1b before sending configuration request.
+        * We need it before checking Link Training (LT) bit becuase
+        * LT is still set even after DLLLA bit is set on some platform.
+        */
+       msleep(1000);
+
        retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
        if (retval) {
                ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
@@ -294,6 +302,16 @@ int pciehp_check_link_status(struct controller *ctrl)
                return retval;
        }
 
+       /*
+        * If the port supports Link speeds greater than 5.0 GT/s, we
+        * must wait for 100 ms after Link training completes before
+        * sending configuration request.
+        */
+       if (ctrl->pcie->port->subordinate->max_bus_speed > PCIE_SPEED_5_0GT)
+               msleep(100);
+
+       pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
+
        return retval;
 }
 
@@ -484,7 +502,6 @@ int pciehp_power_on_slot(struct slot * slot)
        u16 slot_cmd;
        u16 cmd_mask;
        u16 slot_status;
-       u16 lnk_status;
        int retval = 0;
 
        /* Clear sticky power-fault bit from previous power failures */
@@ -516,14 +533,6 @@ int pciehp_power_on_slot(struct slot * slot)
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
                 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
 
-       retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n",
-                               __func__);
-               return retval;
-       }
-       pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
-
        return retval;
 }
 
index aca972bbfb4c8ba04e7fc74efd74636ebe49ea65..dd7e0c51a33e5e5f79eb9f11b444fe4667d2ba2d 100644 (file)
@@ -278,8 +278,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
 
 static int is_shpc_capable(struct pci_dev *dev)
 {
-       if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
-                                               PCI_DEVICE_ID_AMD_GOLAM_7450))
+       if (dev->vendor == PCI_VENDOR_ID_AMD &&
+           dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
                return 1;
        if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
                return 0;
index 36547f0ce305e987c7a414a47d6a4e5806b239cb..75ba2311b54f3f37b62176a37e032c480be9f3f1 100644 (file)
@@ -944,8 +944,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
        ctrl->pci_dev = pdev;  /* pci_dev of the P2P bridge */
        ctrl_dbg(ctrl, "Hotplug Controller:\n");
 
-       if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
-                               PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+       if (pdev->vendor == PCI_VENDOR_ID_AMD &&
+           pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450) {
                /* amd shpc driver doesn't use Base Offset; assume 0 */
                ctrl->mmio_base = pci_resource_start(pdev, 0);
                ctrl->mmio_size = pci_resource_len(pdev, 0);
index ef566443f945253ed94c6dab7d27bf81fcf46d7c..e17e2f8001d2a6ebb770d4e20c6aa0a3cd2576cd 100644 (file)
@@ -2,23 +2,17 @@
 # PINCTRL infrastructure and drivers
 #
 
-menuconfig PINCTRL
-       bool "PINCTRL Support"
+config PINCTRL
+       bool
        depends on EXPERIMENTAL
-       help
-         This enables the PINCTRL subsystem for controlling pins
-         on chip packages, for example multiplexing pins on primarily
-         PGA and BGA packages for systems on chip.
-
-         If unsure, say N.
 
 if PINCTRL
 
+menu "Pin controllers"
+       depends on PINCTRL
+
 config PINMUX
        bool "Support pinmux controllers"
-       help
-         Say Y here if you want the pincontrol subsystem to handle pin
-         multiplexing drivers.
 
 config DEBUG_PINCTRL
        bool "Debug PINCTRL calls"
@@ -30,14 +24,12 @@ config PINMUX_SIRF
        bool "CSR SiRFprimaII pinmux driver"
        depends on ARCH_PRIMA2
        select PINMUX
-       help
-         Say Y here to enable the SiRFprimaII pinmux driver
 
 config PINMUX_U300
        bool "U300 pinmux driver"
        depends on ARCH_U300
        select PINMUX
-       help
-         Say Y here to enable the U300 pinmux driver
+
+endmenu
 
 endif
index f4e3d82379d7869f39f479b74484e3b28dda5140..7f43cf86d77602675297aaea32932c9a176f4c07 100644 (file)
@@ -83,8 +83,10 @@ config DELL_LAPTOP
        depends on EXPERIMENTAL
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL || RFKILL = n
-       depends on POWER_SUPPLY
        depends on SERIO_I8042
+       select POWER_SUPPLY
+       select LEDS_CLASS
+       select NEW_LEDS
        default n
        ---help---
        This driver adds support for rfkill and backlight control to Dell
index a43cfd906c6d678759d241a3fae9363889e1c15d..d93e962f26100c7e0498f80f7dac437c6f0e87f5 100644 (file)
@@ -589,14 +589,14 @@ static const struct backlight_ops dell_ops = {
        .update_status  = dell_send_intensity,
 };
 
-static void touchpad_led_on()
+static void touchpad_led_on(void)
 {
        int command = 0x97;
        char data = 1;
        i8042_command(&data, command | 1 << 12);
 }
 
-static void touchpad_led_off()
+static void touchpad_led_off(void)
 {
        int command = 0x97;
        char data = 2;
index bbf3edd85beb0c404b4e5b7791cfd1b79908dc3a..5be4a392a3aea39b0205baabad87f3535524c5e6 100644 (file)
@@ -509,15 +509,12 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
                                            struct acpi_resource_dma *p)
 {
        int i;
-       unsigned char map = 0, flags = 0;
-
-       if (p->channel_count == 0)
-               flags |= IORESOURCE_DISABLED;
+       unsigned char map = 0, flags;
 
        for (i = 0; i < p->channel_count; i++)
                map |= 1 << p->channels[i];
 
-       flags |= dma_flags(dev, p->type, p->bus_master, p->transfer);
+       flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
        pnp_register_dma_resource(dev, option_flags, map, flags);
 }
 
@@ -527,17 +524,14 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
 {
        int i;
        pnp_irq_mask_t map;
-       unsigned char flags = 0;
-
-       if (p->interrupt_count == 0)
-               flags |= IORESOURCE_DISABLED;
+       unsigned char flags;
 
        bitmap_zero(map.bits, PNP_IRQ_NR);
        for (i = 0; i < p->interrupt_count; i++)
                if (p->interrupts[i])
                        __set_bit(p->interrupts[i], map.bits);
 
-       flags |= irq_flags(p->triggering, p->polarity, p->sharable);
+       flags = irq_flags(p->triggering, p->polarity, p->sharable);
        pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
@@ -547,10 +541,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
 {
        int i;
        pnp_irq_mask_t map;
-       unsigned char flags = 0;
-
-       if (p->interrupt_count == 0)
-               flags |= IORESOURCE_DISABLED;
+       unsigned char flags;
 
        bitmap_zero(map.bits, PNP_IRQ_NR);
        for (i = 0; i < p->interrupt_count; i++) {
@@ -564,7 +555,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
                }
        }
 
-       flags |= irq_flags(p->triggering, p->polarity, p->sharable);
+       flags = irq_flags(p->triggering, p->polarity, p->sharable);
        pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
@@ -574,11 +565,8 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
 {
        unsigned char flags = 0;
 
-       if (io->address_length == 0)
-               flags |= IORESOURCE_DISABLED;
-
        if (io->io_decode == ACPI_DECODE_16)
-               flags |= IORESOURCE_IO_16BIT_ADDR;
+               flags = IORESOURCE_IO_16BIT_ADDR;
        pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
                                   io->alignment, io->address_length, flags);
 }
@@ -587,13 +575,8 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
                                        unsigned int option_flags,
                                        struct acpi_resource_fixed_io *io)
 {
-       unsigned char flags = 0;
-
-       if (io->address_length == 0)
-               flags |= IORESOURCE_DISABLED;
-
        pnp_register_port_resource(dev, option_flags, io->address, io->address,
-                                  0, io->address_length, flags | IORESOURCE_IO_FIXED);
+                                  0, io->address_length, IORESOURCE_IO_FIXED);
 }
 
 static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
@@ -602,11 +585,8 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
 {
        unsigned char flags = 0;
 
-       if (p->address_length == 0)
-               flags |= IORESOURCE_DISABLED;
-
        if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-               flags |= IORESOURCE_MEM_WRITEABLE;
+               flags = IORESOURCE_MEM_WRITEABLE;
        pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
                                  p->alignment, p->address_length, flags);
 }
@@ -617,11 +597,8 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
 {
        unsigned char flags = 0;
 
-       if (p->address_length == 0)
-               flags |= IORESOURCE_DISABLED;
-
        if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-               flags |= IORESOURCE_MEM_WRITEABLE;
+               flags = IORESOURCE_MEM_WRITEABLE;
        pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
                                  p->alignment, p->address_length, flags);
 }
@@ -632,11 +609,8 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
 {
        unsigned char flags = 0;
 
-       if (p->address_length == 0)
-               flags |= IORESOURCE_DISABLED;
-
        if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-               flags |= IORESOURCE_MEM_WRITEABLE;
+               flags = IORESOURCE_MEM_WRITEABLE;
        pnp_register_mem_resource(dev, option_flags, p->address, p->address,
                                  0, p->address_length, flags);
 }
@@ -656,19 +630,16 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
                return;
        }
 
-       if (p->address_length == 0)
-               flags |= IORESOURCE_DISABLED;
-
        if (p->resource_type == ACPI_MEMORY_RANGE) {
                if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
-                       flags |= IORESOURCE_MEM_WRITEABLE;
+                       flags = IORESOURCE_MEM_WRITEABLE;
                pnp_register_mem_resource(dev, option_flags, p->minimum,
                                          p->minimum, 0, p->address_length,
                                          flags);
        } else if (p->resource_type == ACPI_IO_RANGE)
                pnp_register_port_resource(dev, option_flags, p->minimum,
                                           p->minimum, 0, p->address_length,
-                                          flags | IORESOURCE_IO_FIXED);
+                                          IORESOURCE_IO_FIXED);
 }
 
 static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
@@ -678,19 +649,16 @@ static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
        struct acpi_resource_extended_address64 *p = &r->data.ext_address64;
        unsigned char flags = 0;
 
-       if (p->address_length == 0)
-               flags |= IORESOURCE_DISABLED;
-
        if (p->resource_type == ACPI_MEMORY_RANGE) {
                if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
-                       flags |= IORESOURCE_MEM_WRITEABLE;
+                       flags = IORESOURCE_MEM_WRITEABLE;
                pnp_register_mem_resource(dev, option_flags, p->minimum,
                                          p->minimum, 0, p->address_length,
                                          flags);
        } else if (p->resource_type == ACPI_IO_RANGE)
                pnp_register_port_resource(dev, option_flags, p->minimum,
                                           p->minimum, 0, p->address_length,
-                                          flags | IORESOURCE_IO_FIXED);
+                                          IORESOURCE_IO_FIXED);
 }
 
 struct acpipnp_parse_option_s {
index d9fb729535a1691b976d475c5b089bab6fa60cfe..fb7300837feef25a6b2a80de582baf01031bf22a 100644 (file)
@@ -952,7 +952,7 @@ static int ps3_vuart_bus_interrupt_get(void)
        }
 
        result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
-               IRQF_DISABLED, "vuart", &vuart_bus_priv);
+               0, "vuart", &vuart_bus_priv);
 
        if (result) {
                pr_debug("%s:%d: request_irq failed (%d)\n",
index cc328dec946b3766b6531914fba56da244378591..8c3f5adf1bc65378565406b8cb6567f5fd38e894 100644 (file)
@@ -167,7 +167,7 @@ int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
                goto fail_close_device;
        }
 
-       error = request_irq(dev->irq, handler, IRQF_DISABLED,
+       error = request_irq(dev->irq, handler, 0,
                            dev->sbd.core.driver->name, dev);
        if (error) {
                dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n",
index 5abeb3ac3e8da43df3d58bf677c3ac0e3d17116e..298c6c6a279574561eb24f329b115fe134d274a1 100644 (file)
@@ -160,7 +160,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id)
                        break;
        }
 
-       if (!ri)
+       if (i == ARRAY_SIZE(aat2870_regulators))
                return NULL;
 
        ri->enable_addr = AAT2870_LDO_EN;
index 669d0216022195e36bcb8f59b25cf14de1dff6c9..938398f3e869c57814fc130b9133ac435118214e 100644 (file)
@@ -2799,8 +2799,8 @@ void regulator_unregister(struct regulator_dev *rdev)
        list_del(&rdev->list);
        if (rdev->supply)
                regulator_put(rdev->supply);
-       device_unregister(&rdev->dev);
        kfree(rdev->constraints);
+       device_unregister(&rdev->dev);
        mutex_unlock(&regulator_list_mutex);
 }
 EXPORT_SYMBOL_GPL(regulator_unregister);
index 66d2d60b436a3e7a28092d64a499fd203db764a5..b552aae55b417c7cd9aa97fba33bd61ad0b7e787 100644 (file)
@@ -664,10 +664,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
 
        switch (id) {
        case TPS65910_REG_VDD1:
-               dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                if (dcdc_mult == 1)
                        dcdc_mult--;
-               vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
+               vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
                tps65910_modify_bits(pmic, TPS65910_VDD1,
                                (dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
@@ -675,10 +675,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
                tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel);
                break;
        case TPS65910_REG_VDD2:
-               dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                if (dcdc_mult == 1)
                        dcdc_mult--;
-               vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
+               vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
                tps65910_modify_bits(pmic, TPS65910_VDD2,
                                (dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
@@ -756,9 +756,9 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
        switch (id) {
        case TPS65910_REG_VDD1:
        case TPS65910_REG_VDD2:
-               mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                volt = VDD1_2_MIN_VOLT +
-                               (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET;
+                               (selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET;
                break;
        case TPS65911_REG_VDDCTRL:
                volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET);
@@ -947,6 +947,8 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
 
                if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) {
                        pmic->desc[i].ops = &tps65910_ops_dcdc;
+                       pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE *
+                                                       VDD1_2_NUM_VOLT_COARSE;
                } else if (i == TPS65910_REG_VDD3) {
                        if (tps65910_chip_id(tps65910) == TPS65910)
                                pmic->desc[i].ops = &tps65910_ops_vdd3;
index ee8747f4fa08b187ef2f79dbb51e3f69a770bc21..11cc308d66e925db83fa8c50697e734608aac1b8 100644 (file)
@@ -71,6 +71,7 @@ struct twlreg_info {
 #define VREG_TYPE              1
 #define VREG_REMAP             2
 #define VREG_DEDICATED         3       /* LDO control */
+#define VREG_VOLTAGE_SMPS_4030 9
 /* TWL6030 register offsets */
 #define VREG_TRANS             1
 #define VREG_STATE             2
@@ -514,6 +515,32 @@ static struct regulator_ops twl4030ldo_ops = {
        .get_status     = twl4030reg_get_status,
 };
 
+static int
+twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
+                       unsigned *selector)
+{
+       struct twlreg_info *info = rdev_get_drvdata(rdev);
+       int vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
+
+       twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030,
+               vsel);
+       return 0;
+}
+
+static int twl4030smps_get_voltage(struct regulator_dev *rdev)
+{
+       struct twlreg_info *info = rdev_get_drvdata(rdev);
+       int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
+               VREG_VOLTAGE_SMPS_4030);
+
+       return vsel * 12500 + 600000;
+}
+
+static struct regulator_ops twl4030smps_ops = {
+       .set_voltage    = twl4030smps_set_voltage,
+       .get_voltage    = twl4030smps_get_voltage,
+};
+
 static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
@@ -856,6 +883,21 @@ static struct regulator_ops twlsmps_ops = {
                }, \
        }
 
+#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \
+       { \
+       .base = offset, \
+       .id = num, \
+       .delay = turnon_delay, \
+       .remap = remap_conf, \
+       .desc = { \
+               .name = #label, \
+               .id = TWL4030_REG_##label, \
+               .ops = &twl4030smps_ops, \
+               .type = REGULATOR_VOLTAGE, \
+               .owner = THIS_MODULE, \
+               }, \
+       }
+
 #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \
        .base = offset, \
        .min_mV = min_mVolts, \
@@ -947,8 +989,8 @@ static struct twlreg_info twl_regs[] = {
        TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08),
        TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08),
        TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08),
-       TWL4030_ADJUSTABLE_LDO(VDD1, 0x55, 15, 1000, 0x08),
-       TWL4030_ADJUSTABLE_LDO(VDD2, 0x63, 16, 1000, 0x08),
+       TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08),
+       TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08),
        TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08),
        TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08),
        TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08),
index d33544802a2ea5fc023390a069bcbc1f9d147a41..bb21f443fb7038719458d03c97e4b4eb00a225a1 100644 (file)
@@ -76,12 +76,15 @@ static inline unsigned char vrtc_is_updating(void)
 /*
  * rtc_time's year contains the increment over 1900, but vRTC's YEAR
  * register can't be programmed to value larger than 0x64, so vRTC
- * driver chose to use 1960 (1970 is UNIX time start point) as the base,
+ * driver chose to use 1972 (1970 is UNIX time start point) as the base,
  * and does the translation at read/write time.
  *
- * Why not just use 1970 as the offset? it's because using 1960 will
+ * Why not just use 1970 as the offset? it's because using 1972 will
  * make it consistent in leap year setting for both vrtc and low-level
- * physical rtc devices.
+ * physical rtc devices. Then why not use 1960 as the offset? If we use
+ * 1960, for a device's first use, its YEAR register is 0 and the system
+ * year will be parsed as 1960 which is not a valid UNIX time and will
+ * cause many applications to fail mysteriously.
  */
 static int mrst_read_time(struct device *dev, struct rtc_time *time)
 {
@@ -99,10 +102,10 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
        time->tm_year = vrtc_cmos_read(RTC_YEAR);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       /* Adjust for the 1960/1900 */
-       time->tm_year += 60;
+       /* Adjust for the 1972/1900 */
+       time->tm_year += 72;
        time->tm_mon--;
-       return RTC_24H;
+       return rtc_valid_tm(time);
 }
 
 static int mrst_set_time(struct device *dev, struct rtc_time *time)
@@ -119,9 +122,9 @@ static int mrst_set_time(struct device *dev, struct rtc_time *time)
        min = time->tm_min;
        sec = time->tm_sec;
 
-       if (yrs < 70 || yrs > 138)
+       if (yrs < 72 || yrs > 138)
                return -EINVAL;
-       yrs -= 60;
+       yrs -= 72;
 
        spin_lock_irqsave(&rtc_lock, flags);
 
index b3eba3cddd42658f76cb7ec84a3c13187993d1b4..e4b6880aabd05492b2a08c0511f400340b9fc0fa 100644 (file)
@@ -220,7 +220,7 @@ static void puv3_rtc_enable(struct platform_device *pdev, int en)
        }
 }
 
-static int puv3_rtc_remove(struct platform_device *dev)
+static int __devexit puv3_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
@@ -236,7 +236,7 @@ static int puv3_rtc_remove(struct platform_device *dev)
        return 0;
 }
 
-static int puv3_rtc_probe(struct platform_device *pdev)
+static int __devinit puv3_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct resource *res;
index 43068fbd0baacfe8beb7d353cda35a8c06c371e2..1b6d9247fdc78a4237d5e7048347a0a66875d140 100644 (file)
@@ -641,6 +641,8 @@ static int __init zcore_init(void)
 
        if (ipl_info.type != IPL_TYPE_FCP_DUMP)
                return -ENODATA;
+       if (OLDMEM_BASE)
+               return -ENODATA;
 
        zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long));
        debug_register_view(zcore_dbf, &debug_sprintf_view);
index b77ae519d79c4eea8c6d87a1e08609dc70ae0276..ec94f049e99543849ed56c90c665102c40c5b87e 100644 (file)
@@ -1271,18 +1271,16 @@ ap_config_timeout(unsigned long ptr)
 }
 
 /**
- * ap_schedule_poll_timer(): Schedule poll timer.
+ * __ap_schedule_poll_timer(): Schedule poll timer.
  *
  * Set up the timer to run the poll tasklet
  */
-static inline void ap_schedule_poll_timer(void)
+static inline void __ap_schedule_poll_timer(void)
 {
        ktime_t hr_time;
 
        spin_lock_bh(&ap_poll_timer_lock);
-       if (ap_using_interrupts() || ap_suspend_flag)
-               goto out;
-       if (hrtimer_is_queued(&ap_poll_timer))
+       if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
                goto out;
        if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
                hr_time = ktime_set(0, poll_timeout);
@@ -1293,6 +1291,18 @@ out:
        spin_unlock_bh(&ap_poll_timer_lock);
 }
 
+/**
+ * ap_schedule_poll_timer(): Schedule poll timer.
+ *
+ * Set up the timer to run the poll tasklet
+ */
+static inline void ap_schedule_poll_timer(void)
+{
+       if (ap_using_interrupts())
+               return;
+       __ap_schedule_poll_timer();
+}
+
 /**
  * ap_poll_read(): Receive pending reply messages from an AP device.
  * @ap_dev: pointer to the AP device
@@ -1374,8 +1384,9 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
                        *flags |= 1;
                *flags |= 2;
                break;
-       case AP_RESPONSE_Q_FULL:
        case AP_RESPONSE_RESET_IN_PROGRESS:
+               __ap_schedule_poll_timer();
+       case AP_RESPONSE_Q_FULL:
                *flags |= 2;
                break;
        case AP_RESPONSE_MESSAGE_TOO_BIG:
index fa80ba1f0344318a30697cf09af4a44cb135f857..9b66d2d1809b30647c2db82c88ba62306f2061b3 100644 (file)
@@ -4,7 +4,7 @@ menu "S/390 network device drivers"
 config LCS
        def_tristate m
        prompt "Lan Channel Station Interface"
-       depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI)
+       depends on CCW && NETDEVICES && (ETHERNET || TR || FDDI)
        help
           Select this option if you want to use LCS networking on IBM System z.
           This device driver supports Token Ring (IEEE 802.5),
index c28713da1ec5d380f9e904bab6f2946016cb76ec..863fc2197155c36c0f956cd9d3bb7781d8b46778 100644 (file)
@@ -50,7 +50,7 @@
 #include "lcs.h"
 
 
-#if !defined(CONFIG_NET_ETHERNET) && \
+#if !defined(CONFIG_ETHERNET) && \
     !defined(CONFIG_TR) && !defined(CONFIG_FDDI)
 #error Cannot compile lcs.c without some net devices switched on.
 #endif
@@ -1634,7 +1634,7 @@ lcs_startlan_auto(struct lcs_card *card)
        int rc;
 
        LCS_DBF_TEXT(2, trace, "strtauto");
-#ifdef CONFIG_NET_ETHERNET
+#ifdef CONFIG_ETHERNET
        card->lan_type = LCS_FRAME_TYPE_ENET;
        rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP);
        if (rc == 0)
@@ -2166,7 +2166,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
                goto netdev_out;
        }
        switch (card->lan_type) {
-#ifdef CONFIG_NET_ETHERNET
+#ifdef CONFIG_ETHERNET
        case LCS_FRAME_TYPE_ENET:
                card->lan_type_trans = eth_type_trans;
                dev = alloc_etherdev(0);
index 3251333a23df18b6e8f378f0f681ac818145f0e1..b6a6356d09b3a52857a1f47f14d1a2241b04e142 100644 (file)
@@ -1994,6 +1994,8 @@ static struct net_device *netiucv_init_netdevice(char *username)
                           netiucv_setup_netdevice);
        if (!dev)
                return NULL;
+       if (dev_alloc_name(dev, dev->name) < 0)
+               goto out_netdev;
 
        privptr = netdev_priv(dev);
        privptr->fsm = init_fsm("netiucvdev", dev_state_names,
index b77c65ed13812f9d7e5462c0bcb5bcb9c1fa33f1..4abc79d3963f86ee2dc7dfd14c1fb240bf2eb540 100644 (file)
@@ -236,8 +236,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
 #define QETH_IN_BUF_COUNT_MAX 128
 #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
 #define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
-               ((card)->ssqd.qdioac1 & AC1_SIGA_INPUT_NEEDED ? 1 : \
-                ((card)->qdio.in_buf_pool.buf_count / 2))
+                ((card)->qdio.in_buf_pool.buf_count / 2)
 
 /* buffers we have to be behind before we get a PCI */
 #define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
index 81534437373a3c1209c914db4fb2a32d45860e44..fff57de78943c6d55cda3ece38a22f69bcda76b1 100644 (file)
@@ -881,7 +881,6 @@ EXPORT_SYMBOL_GPL(qeth_do_run_thread);
 void qeth_schedule_recovery(struct qeth_card *card)
 {
        QETH_CARD_TEXT(card, 2, "startrec");
-       WARN_ON(1);
        if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
                schedule_work(&card->kernel_thread_starter);
 }
index e4c1176ee25b2fd9942cfad447826611bbc7037f..4d5307ddbe55b03ce78b89e423369927c171c2c1 100644 (file)
@@ -2756,11 +2756,13 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
        struct neighbour *n = NULL;
        struct dst_entry *dst;
 
+       rcu_read_lock();
        dst = skb_dst(skb);
        if (dst)
                n = dst_get_neighbour(dst);
        if (n) {
                cast_type = n->type;
+               rcu_read_unlock();
                if ((cast_type == RTN_BROADCAST) ||
                    (cast_type == RTN_MULTICAST) ||
                    (cast_type == RTN_ANYCAST))
@@ -2768,6 +2770,8 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
                else
                        return RTN_UNSPEC;
        }
+       rcu_read_unlock();
+
        /* try something else */
        if (skb->protocol == ETH_P_IPV6)
                return (skb_network_header(skb)[24] == 0xff) ?
@@ -2847,6 +2851,8 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
        }
 
        hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+
+       rcu_read_lock();
        dst = skb_dst(skb);
        if (dst)
                n = dst_get_neighbour(dst);
@@ -2893,6 +2899,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
                                QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
                }
        }
+       rcu_read_unlock();
 }
 
 static inline void qeth_l3_hdr_csum(struct qeth_card *card,
index 0ea2fbfe0e993a42932221d52f0040aaf52b96db..d979bb26522ff8348df72caa8d2c5871deb7f5b4 100644 (file)
@@ -335,10 +335,10 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
                                        QETH_IN_BUF_COUNT_MAX)
                                qeth_realloc_buffer_pool(card,
                                        QETH_IN_BUF_COUNT_MAX);
-                       break;
                } else
                        rc = -EPERM;
-       default:   /* fall through */
+               break;
+       default:
                rc = -EINVAL;
        }
 out:
index 4aa76d6f11dfed870db05bb098f13cf4aa3d361a..705e13e470af18850ae4375533ae4f85495b592c 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
@@ -1109,6 +1110,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
                unique_id++;
        }
 
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
        error = pci_enable_device(pdev);
        if (error)
                goto out;
index e76107b2ade3a2b7a2666daab0c7a0b683e53d74..865d452542be923ef7c02bc0f4eea816dfc898b3 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -3922,6 +3923,10 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)
                dev_warn(&h->pdev->dev, "controller appears to be disabled\n");
                return -ENODEV;
        }
+
+       pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
+                              PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
+
        err = pci_enable_device(h->pdev);
        if (err) {
                dev_warn(&h->pdev->dev, "unable to enable PCI device\n");
index 8889b1babcacaebdc97d8333d5bdaebf2dd93b88..4e041f6d808cd6e49666b35c8d8aec0f1b0a76c5 100644 (file)
@@ -2802,6 +2802,11 @@ _scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
 
        if (ioc->is_driver_loading)
                return;
+
+       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       if (!fw_event)
+               return;
+
        fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
        fw_event->ioc = ioc;
        _scsih_fw_event_add(ioc, fw_event);
index 06bc26554a67359a8656ef976b6d483e71bfd0fb..f85cfa6c47b5212982bcbfcd9065936c27360f3d 100644 (file)
@@ -1409,6 +1409,8 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
 
        blk_start_request(req);
 
+       scmd_printk(KERN_INFO, cmd, "killing request\n");
+
        sdev = cmd->device;
        starget = scsi_target(sdev);
        shost = sdev->host;
@@ -1490,7 +1492,6 @@ static void scsi_request_fn(struct request_queue *q)
        struct request *req;
 
        if (!sdev) {
-               printk("scsi: killing requests for dead queue\n");
                while ((req = blk_peek_request(q)) != NULL)
                        scsi_kill_request(req, q);
                return;
index 72273a0e56662569931f812b6f628a3e3a4748c8..b3c6d957fbd8aa587dcd039547eaa82bd67b6476 100644 (file)
@@ -319,11 +319,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
        return sdev;
 
 out_device_destroy:
-       scsi_device_set_state(sdev, SDEV_DEL);
-       transport_destroy_device(&sdev->sdev_gendev);
-       put_device(&sdev->sdev_dev);
-       scsi_free_queue(sdev->request_queue);
-       put_device(&sdev->sdev_gendev);
+       __scsi_remove_device(sdev);
 out:
        if (display_failure_msg)
                printk(ALLOC_FAILURE_MSG, __func__);
index 24e6cec0ae8dfb51efbb704f6e37d0228ddcc3fe..67e272ab162310645f0c3339c7cd29987f3b4dd8 100644 (file)
@@ -7,3 +7,11 @@ obj-$(CONFIG_HAVE_CLK)         += clk/
 obj-$(CONFIG_MAPLE)            += maple/
 obj-$(CONFIG_SUPERHYWAY)       += superhyway/
 obj-$(CONFIG_GENERIC_GPIO)     += pfc.o
+
+#
+# For the moment we only use this framework for ARM-based SH/R-Mobile
+# platforms and generic SH. SH-based SH-Mobile platforms are still using
+# an older framework that is pending up-porting, at which point this
+# special casing can go away.
+#
+obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE)    += pm_runtime.o
index dc8d022c07a1505b2cc0bd86ccfb2e097c6f1f16..db257a35e71a545aa724b97d40dbdd6dbf1fe7f2 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/seq_file.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/debugfs.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/sh_clk.h>
@@ -173,6 +172,26 @@ long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
        return clk_rate_round_helper(&div_range_round);
 }
 
+static long clk_rate_mult_range_iter(unsigned int pos,
+                                     struct clk_rate_round_data *rounder)
+{
+       return clk_get_rate(rounder->arg) * pos;
+}
+
+long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min,
+                              unsigned int mult_max, unsigned long rate)
+{
+       struct clk_rate_round_data mult_range_round = {
+               .min    = mult_min,
+               .max    = mult_max,
+               .func   = clk_rate_mult_range_iter,
+               .arg    = clk_get_parent(clk),
+               .rate   = rate,
+       };
+
+       return clk_rate_round_helper(&mult_range_round);
+}
+
 int clk_rate_table_find(struct clk *clk,
                        struct cpufreq_frequency_table *freq_table,
                        unsigned long rate)
@@ -205,9 +224,6 @@ int clk_reparent(struct clk *child, struct clk *parent)
                list_add(&child->sibling, &parent->children);
        child->parent = parent;
 
-       /* now do the debugfs renaming to reattach the child
-          to the proper parent */
-
        return 0;
 }
 
@@ -665,89 +681,6 @@ static int __init clk_syscore_init(void)
 subsys_initcall(clk_syscore_init);
 #endif
 
-/*
- *     debugfs support to trace clock tree hierarchy and attributes
- */
-static struct dentry *clk_debugfs_root;
-
-static int clk_debugfs_register_one(struct clk *c)
-{
-       int err;
-       struct dentry *d;
-       struct clk *pa = c->parent;
-       char s[255];
-       char *p = s;
-
-       p += sprintf(p, "%p", c);
-       d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
-       if (!d)
-               return -ENOMEM;
-       c->dentry = d;
-
-       d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       return 0;
-
-err_out:
-       debugfs_remove_recursive(c->dentry);
-       return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
-       int err;
-       struct clk *pa = c->parent;
-
-       if (pa && !pa->dentry) {
-               err = clk_debugfs_register(pa);
-               if (err)
-                       return err;
-       }
-
-       if (!c->dentry) {
-               err = clk_debugfs_register_one(c);
-               if (err)
-                       return err;
-       }
-       return 0;
-}
-
-static int __init clk_debugfs_init(void)
-{
-       struct clk *c;
-       struct dentry *d;
-       int err;
-
-       d = debugfs_create_dir("clock", NULL);
-       if (!d)
-               return -ENOMEM;
-       clk_debugfs_root = d;
-
-       list_for_each_entry(c, &clock_list, node) {
-               err = clk_debugfs_register(c);
-               if (err)
-                       goto err_out;
-       }
-       return 0;
-err_out:
-       debugfs_remove_recursive(clk_debugfs_root);
-       return err;
-}
-late_initcall(clk_debugfs_init);
-
 static int __init clk_late_init(void)
 {
        unsigned long flags;
diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c
new file mode 100644 (file)
index 0000000..afe9282
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Runtime PM support code
+ *
+ *  Copyright (C) 2009-2010 Magnus Damm
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_clock.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/sh_clk.h>
+#include <linux/bitmap.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int default_platform_runtime_idle(struct device *dev)
+{
+       /* suspend synchronously to disable clocks immediately */
+       return pm_runtime_suspend(dev);
+}
+
+static struct dev_pm_domain default_pm_domain = {
+       .ops = {
+               .runtime_suspend = pm_clk_suspend,
+               .runtime_resume = pm_clk_resume,
+               .runtime_idle = default_platform_runtime_idle,
+               USE_PLATFORM_PM_SLEEP_OPS
+       },
+};
+
+#define DEFAULT_PM_DOMAIN_PTR  (&default_pm_domain)
+
+#else
+
+#define DEFAULT_PM_DOMAIN_PTR  NULL
+
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct pm_clk_notifier_block platform_bus_notifier = {
+       .pm_domain = DEFAULT_PM_DOMAIN_PTR,
+       .con_ids = { NULL, },
+};
+
+static int __init sh_pm_runtime_init(void)
+{
+       pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+       return 0;
+}
+core_initcall(sh_pm_runtime_init);
+
+static int __init sh_pm_runtime_late_init(void)
+{
+       pm_genpd_poweroff_unused();
+       return 0;
+}
+late_initcall(sh_pm_runtime_late_init);
index 79665e2e6ec524b89f02c6aa680ca5b133009fa9..16d6a839c7faca2ea0f2bd7a948036d546fc46b6 100644 (file)
@@ -907,7 +907,7 @@ static void atmel_spi_cleanup(struct spi_device *spi)
 
 /*-------------------------------------------------------------------------*/
 
-static int __init atmel_spi_probe(struct platform_device *pdev)
+static int __devinit atmel_spi_probe(struct platform_device *pdev)
 {
        struct resource         *regs;
        int                     irq;
@@ -1003,7 +1003,7 @@ out_free:
        return ret;
 }
 
-static int __exit atmel_spi_remove(struct platform_device *pdev)
+static int __devexit atmel_spi_remove(struct platform_device *pdev)
 {
        struct spi_master       *master = platform_get_drvdata(pdev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
@@ -1072,6 +1072,7 @@ static struct platform_driver atmel_spi_driver = {
        },
        .suspend        = atmel_spi_suspend,
        .resume         = atmel_spi_resume,
+       .probe          = atmel_spi_probe,
        .remove         = __exit_p(atmel_spi_remove),
 };
 module_platform_driver(atmel_spi_driver);
index e763254741c296169b6d662d5f398c1a90170cc2..21c70b2b83119e333ebe4c5b5e18ab70f2ce6a0a 100644 (file)
@@ -426,7 +426,7 @@ static int __devinit nuc900_spi_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       mfp_set_groupg(&pdev->dev);
+       mfp_set_groupg(&pdev->dev, NULL);
        nuc900_init_spi(hw);
 
        err = spi_bitbang_start(&hw->bitbang);
index f103e470cb6362e248a264576e457e03f0ab5409..5559b229919870fad59680b722e1390585ba61ca 100644 (file)
@@ -2184,6 +2184,12 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
                goto  err_clk_prep;
        }
 
+       status = clk_enable(pl022->clk);
+       if (status) {
+               dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
+               goto err_no_clk_en;
+       }
+
        /* Disable SSP */
        writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
               SSP_CR1(pl022->virtbase));
@@ -2237,6 +2243,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 
        free_irq(adev->irq[0], pl022);
  err_no_irq:
+       clk_disable(pl022->clk);
+ err_no_clk_en:
        clk_unprepare(pl022->clk);
  err_clk_prep:
        clk_put(pl022->clk);
index 9e1864c6dfd08caf355f1e0c3aa347d6b0386beb..8190f2aaf53bb88aaea8df5c025d6f83c2ee68d1 100644 (file)
@@ -1,6 +1,7 @@
 config ET131X
        tristate "Agere ET-1310 Gigabit Ethernet support"
-       depends on PCI
+       depends on PCI && NET && NETDEVICES
+       select PHYLIB
        default n
        ---help---
          This driver supports Agere ET-1310 ethernet adapters.
index f5f44a02456fd5aa20ae06b9b524dee1b1c01757..0c1c6ca8c3794de60d440f3dc33bb60f8ebb2e83 100644 (file)
@@ -4469,6 +4469,12 @@ static int et131x_resume(struct device *dev)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume);
+#define ET131X_PM_OPS (&et131x_pm_ops)
+#else
+#define ET131X_PM_OPS NULL
+#endif
+
 /* ISR functions */
 
 /**
@@ -5470,12 +5476,6 @@ err_out:
        return result;
 }
 
-static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume);
-#define ET131X_PM_OPS (&et131x_pm_ops)
-#else
-#define ET131X_PM_OPS NULL
-#endif
-
 static DEFINE_PCI_DEVICE_TABLE(et131x_pci_table) = {
        { PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_GIG), 0UL},
        { PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_FAST), 0UL},
index 326e967d54ef035258e7d4c325c4d6c26d731edc..aec9311b108c7c73b2b599c42976cbe99e1ca8b2 100644 (file)
@@ -242,19 +242,26 @@ static const struct file_operations iio_event_chrdev_fileops = {
 
 static int iio_event_getfd(struct iio_dev *indio_dev)
 {
-       if (indio_dev->event_interface == NULL)
+       struct iio_event_interface *ev_int = indio_dev->event_interface;
+       int fd;
+
+       if (ev_int == NULL)
                return -ENODEV;
 
-       mutex_lock(&indio_dev->event_interface->event_list_lock);
-       if (test_and_set_bit(IIO_BUSY_BIT_POS,
-                            &indio_dev->event_interface->flags)) {
-               mutex_unlock(&indio_dev->event_interface->event_list_lock);
+       mutex_lock(&ev_int->event_list_lock);
+       if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
+               mutex_unlock(&ev_int->event_list_lock);
                return -EBUSY;
        }
-       mutex_unlock(&indio_dev->event_interface->event_list_lock);
-       return anon_inode_getfd("iio:event",
-                               &iio_event_chrdev_fileops,
-                               indio_dev->event_interface, O_RDONLY);
+       mutex_unlock(&ev_int->event_list_lock);
+       fd = anon_inode_getfd("iio:event",
+                               &iio_event_chrdev_fileops, ev_int, O_RDONLY);
+       if (fd < 0) {
+               mutex_lock(&ev_int->event_list_lock);
+               clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
+               mutex_unlock(&ev_int->event_list_lock);
+       }
+       return fd;
 }
 
 static int __init iio_init(void)
index d335c7d6fa0f849ac22dbdbe526948dafb5e872b..828526d4c28985221e6b6ebba019053e1a137d21 100644 (file)
@@ -32,8 +32,8 @@
 #include "as102_fw.h"
 #include "dvbdev.h"
 
-int debug;
-module_param_named(debug, debug, int, 0644);
+int as102_debug;
+module_param_named(debug, as102_debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)");
 
 int dual_tuner;
index bcda635b5a9967454f95c843ccf4ae4c42a22d15..fd33f5a12dcc2167cf9dada508b13521f7159b8f 100644 (file)
@@ -37,7 +37,8 @@ extern struct spi_driver as102_spi_driver;
 #define DRIVER_FULL_NAME "Abilis Systems as10x usb driver"
 #define DRIVER_NAME "as10x_usb"
 
-extern int debug;
+extern int as102_debug;
+#define debug  as102_debug
 
 #define dprintk(debug, args...) \
        do { if (debug) {       \
index b445cd63f901dc4299d55eef54c6675151d8387a..2542c37439049e8e878f29600b8d08c7f6635cd3 100644 (file)
@@ -275,7 +275,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
                CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64;
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                        struct skb_frag_struct *fs = skb_shinfo(skb)->frags + i;
-                       hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page) + fs->page_offset));
+                       hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page.p) + fs->page_offset));
                        hw_buffer.s.size = fs->size;
                        CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64;
                }
index 5cde96b2e6e17d10c71f03a1e8e13fcb78179e6a..5c2a15b42dfede39997352cc7289871bd4dfd161 100644 (file)
@@ -1,6 +1,6 @@
 config SLICOSS
        tristate "Alacritech Gigabit IS-NIC support"
-       depends on PCI && X86
+       depends on PCI && X86 && NET
        default n
        help
          This driver supports Alacritech's IS-NIC gigabit ethernet cards.
index 2bd34662beb5bea4e8606bbc3dcaf20f64d4b6f6..a9c309a167c2d43f71c79b670a4e00d6e76b567f 100644 (file)
@@ -340,7 +340,7 @@ u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block,
                struct mtd_oob_ops ops;
                int ret;
 
-               ops.mode = MTD_OOB_AUTO;
+               ops.mode = MTD_OPS_AUTO_OOB;
                ops.datbuf = read_data;
                ops.len = DeviceInfo.wPageDataSize;
                ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
@@ -400,7 +400,7 @@ u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block,
                struct mtd_oob_ops ops;
                int ret;
 
-               ops.mode = MTD_OOB_AUTO;
+               ops.mode = MTD_OPS_AUTO_OOB;
                ops.datbuf = write_data;
                ops.len = DeviceInfo.wPageDataSize;
                ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
@@ -473,7 +473,7 @@ u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block,
                struct mtd_oob_ops ops;
                int ret;
 
-               ops.mode = MTD_OOB_AUTO;
+               ops.mode = MTD_OPS_AUTO_OOB;
                ops.datbuf = NULL;
                ops.len = 0;
                ops.oobbuf = read_data;
index 708f8e92771a6d03c6ef3615571898da0cd1321e..dd9a5743fa991f3fb789d2e17d12563deaead0cd 100644 (file)
@@ -678,10 +678,10 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
                return;
 
        if (delay > 1000)
-               schedule_delayed_work(&(tz->poll_queue),
+               queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
                                      round_jiffies(msecs_to_jiffies(delay)));
        else
-               schedule_delayed_work(&(tz->poll_queue),
+               queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
                                      msecs_to_jiffies(delay));
 }
 
index 435f6facbc238606feeea4ce26b508ed34ddb6af..44fbebab5075f98f337d880288993b01ad9e7271 100644 (file)
@@ -46,6 +46,7 @@ static inline char __dcc_getchar(void)
 
        asm volatile("mrc p14, 0, %0, c0, c5, 0 @ read comms data reg"
                : "=r" (__c));
+       isb();
 
        return __c;
 }
@@ -55,6 +56,7 @@ static inline void __dcc_putchar(char c)
        asm volatile("mcr p14, 0, %0, c0, c5, 0 @ write a char"
                : /* no output register */
                : "r" (c));
+       isb();
 }
 
 static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
index 4cb0d0a3e57b774c22d6a8909cc20a7615c6ed60..fc7bbba585cee2c2b0d5282c42fb986bfb032a0a 100644 (file)
 static int debug;
 module_param(debug, int, 0600);
 
-#define T1     (HZ/10)
-#define T2     (HZ/3)
-#define N2     3
+/* Defaults: these are from the specification */
+
+#define T1     10              /* 100mS */
+#define T2     34              /* 333mS */
+#define N2     3               /* Retry 3 times */
 
 /* Use long timers for testing at low speed with debug on */
 #ifdef DEBUG_TIMING
-#define T1     HZ
-#define T2     (2 * HZ)
+#define T1     100
+#define T2     200
 #endif
 
 /*
index 5f479dada6f2b25a309b48c50d5b2dee0a35777d..925a1e547a834f10942ab878357a0568254b6ae8 100644 (file)
@@ -1560,7 +1560,7 @@ config SERIAL_IFX6X60
          Support for the IFX6x60 modem devices on Intel MID platforms.
 
 config SERIAL_PCH_UART
-       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART"
+       tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART"
        depends on PCI
        select SERIAL_CORE
        help
@@ -1568,12 +1568,12 @@ config SERIAL_PCH_UART
          which is an IOH(Input/Output Hub) for x86 embedded processor.
          Enabling PCH_DMA, this PCH UART works as DMA mode.
 
-         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
-         Output Hub), ML7213 and ML7223.
-         ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
-         for MP(Media Phone) use.
-         ML7213/ML7223 is companion chip for Intel Atom E6xx series.
-         ML7213/ML7223 is completely compatible for Intel EG20T PCH.
+         This driver also can be used for LAPIS Semiconductor IOH(Input/
+         Output Hub), ML7213, ML7223 and ML7831.
+         ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
+         for MP(Media Phone) use and ML7831 IOH is for general purpose use.
+         ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
 
 config SERIAL_MSM_SMD
        bool "Enable tty device interface for some SMD ports"
index 4a0f86fa1e90566c03c693c413a581a80e40e7b6..4c823f341d9895cd88a5f0d710f56449714fef86 100644 (file)
@@ -228,7 +228,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
        if (rs485conf->flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
                atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-               if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
+               if ((rs485conf->delay_rts_after_send) > 0)
                        UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
        } else {
@@ -304,7 +304,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 
        if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
-               if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+               if ((atmel_port->rs485.delay_rts_after_send) > 0)
                        UART_PUT_TTGR(port,
                                        atmel_port->rs485.delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
@@ -1228,7 +1228,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
        if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
-               if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+               if ((atmel_port->rs485.delay_rts_after_send) > 0)
                        UART_PUT_TTGR(port,
                                        atmel_port->rs485.delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
@@ -1447,16 +1447,6 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
                rs485conf->delay_rts_after_send = rs485_delay[1];
                rs485conf->flags = 0;
 
-               if (rs485conf->delay_rts_before_send == 0 &&
-                   rs485conf->delay_rts_after_send == 0) {
-                       rs485conf->flags |= SER_RS485_RTS_ON_SEND;
-               } else {
-                       if (rs485conf->delay_rts_before_send)
-                               rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND;
-                       if (rs485conf->delay_rts_after_send)
-                               rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
-               }
-
                if (of_get_property(np, "rs485-rx-during-tx", NULL))
                        rs485conf->flags |= SER_RS485_RX_DURING_TX;
 
index b7435043f2fe90d87d646141060318851ad12a86..1dfba7b779c84ed1f151b490295b0a99751b7b72 100644 (file)
@@ -3234,9 +3234,8 @@ rs_write(struct tty_struct *tty,
                e100_disable_rx(info);
                e100_enable_rx_irq(info);
 #endif
-               if ((info->rs485.flags & SER_RS485_RTS_BEFORE_SEND) &&
-                       (info->rs485.delay_rts_before_send > 0))
-                               msleep(info->rs485.delay_rts_before_send);
+               if (info->rs485.delay_rts_before_send > 0)
+                       msleep(info->rs485.delay_rts_before_send);
        }
 #endif /* CONFIG_ETRAX_RS485 */
 
@@ -3693,10 +3692,6 @@ rs_ioctl(struct tty_struct *tty,
 
                rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send;
                rs485data.flags = 0;
-               if (rs485data.delay_rts_before_send != 0)
-                       rs485data.flags |= SER_RS485_RTS_BEFORE_SEND;
-               else
-                       rs485data.flags &= ~(SER_RS485_RTS_BEFORE_SEND);
 
                if (rs485ctrl.enabled)
                        rs485data.flags |= SER_RS485_ENABLED;
@@ -4531,7 +4526,6 @@ static int __init rs_init(void)
                /* Set sane defaults */
                info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND);
                info->rs485.flags |= SER_RS485_RTS_AFTER_SEND;
-               info->rs485.flags &= ~(SER_RS485_RTS_BEFORE_SEND);
                info->rs485.delay_rts_before_send = 0;
                info->rs485.flags &= ~(SER_RS485_ENABLED);
 #endif
index 286c386d9c4677d16cf0effcf9769f34c9249e52..e272d3919c67fdb6b465902fe7a5cb17978cc3a5 100644 (file)
@@ -884,7 +884,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
 {
        struct uart_hsu_port *up =
                        container_of(port, struct uart_hsu_port, port);
-       struct tty_struct *tty = port->state->port.tty;
        unsigned char cval, fcr = 0;
        unsigned long flags;
        unsigned int baud, quot;
@@ -907,8 +906,7 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 
        /* CMSPAR isn't supported by this driver */
-       if (tty)
-               tty->termios->c_cflag &= ~CMSPAR;
+       termios->c_cflag &= ~CMSPAR;
 
        if (termios->c_cflag & CSTOPB)
                cval |= UART_LCR_STOP;
index 21febef926aa7c31f09ef26dbbbfa34d78f76df1..d6aba8c087e4784370648976c0d018a569c374f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
  *
  *This program is free software; you can redistribute it and/or modify
  *it under the terms of the GNU General Public License as published by
@@ -46,8 +46,8 @@ enum {
 
 /* Set the max number of UART port
  * Intel EG20T PCH: 4 port
- * OKI SEMICONDUCTOR ML7213 IOH: 3 port
- * OKI SEMICONDUCTOR ML7223 IOH: 2 port
+ * LAPIS Semiconductor ML7213 IOH: 3 port
+ * LAPIS Semiconductor ML7223 IOH: 2 port
 */
 #define PCH_UART_NR    4
 
@@ -258,6 +258,8 @@ enum pch_uart_num_t {
        pch_ml7213_uart2,
        pch_ml7223_uart0,
        pch_ml7223_uart1,
+       pch_ml7831_uart0,
+       pch_ml7831_uart1,
 };
 
 static struct pch_uart_driver_data drv_dat[] = {
@@ -270,6 +272,8 @@ static struct pch_uart_driver_data drv_dat[] = {
        [pch_ml7213_uart2] = {PCH_UART_2LINE, 2},
        [pch_ml7223_uart0] = {PCH_UART_8LINE, 0},
        [pch_ml7223_uart1] = {PCH_UART_2LINE, 1},
+       [pch_ml7831_uart0] = {PCH_UART_8LINE, 0},
+       [pch_ml7831_uart1] = {PCH_UART_2LINE, 1},
 };
 
 static unsigned int default_baud = 9600;
@@ -628,6 +632,7 @@ static void pch_request_dma(struct uart_port *port)
                dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n",
                        __func__);
                dma_release_channel(priv->chan_tx);
+               priv->chan_tx = NULL;
                return;
        }
 
@@ -1215,8 +1220,7 @@ static void pch_uart_shutdown(struct uart_port *port)
                dev_err(priv->port.dev,
                        "pch_uart_hal_set_fifo Failed(ret=%d)\n", ret);
 
-       if (priv->use_dma_flag)
-               pch_free_dma(port);
+       pch_free_dma(port);
 
        free_irq(priv->port.irq, priv);
 }
@@ -1280,6 +1284,7 @@ static void pch_uart_set_termios(struct uart_port *port,
        if (rtn)
                goto out;
 
+       pch_uart_set_mctrl(&priv->port, priv->port.mctrl);
        /* Don't rewrite B0 */
        if (tty_termios_baud_rate(termios))
                tty_termios_encode_baud_rate(termios, baud, baud);
@@ -1552,6 +1557,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
         .driver_data = pch_ml7223_uart0},
        {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D),
         .driver_data = pch_ml7223_uart1},
+       {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8811),
+        .driver_data = pch_ml7831_uart0},
+       {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8812),
+        .driver_data = pch_ml7831_uart1},
        {0,},
 };
 
index 1945c70539c2bb8326bdda5ec1e31d7c69980d43..aff9d612dff02a46b38d6b4133d0283dbc3f8468 100644 (file)
@@ -206,6 +206,25 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
                [SCLSR]         = sci_reg_invalid,
        },
 
+       /*
+        * Common SH-2(A) SCIF definitions for ports with FIFO data
+        * count registers.
+        */
+       [SCIx_SH2_SCIF_FIFODATA_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x0c,  8 },
+               [SCxSR]         = { 0x10, 16 },
+               [SCxRDR]        = { 0x14,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = { 0x20, 16 },
+               [SCLSR]         = { 0x24, 16 },
+       },
+
        /*
         * Common SH-3 SCIF definitions.
         */
index 512c49f98e85a2c59e70b2c454877589756376a2..8e0924f55446f963b8b9d79a0d66347d30c982bc 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <linux/kmod.h>
 #include <linux/nsproxy.h>
+#include <linux/ratelimit.h>
 
 /*
  *     This guards the refcounted line discipline lists. The lock
@@ -547,15 +548,16 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
 /**
  *     tty_ldisc_wait_idle     -       wait for the ldisc to become idle
  *     @tty: tty to wait for
+ *     @timeout: for how long to wait at most
  *
  *     Wait for the line discipline to become idle. The discipline must
  *     have been halted for this to guarantee it remains idle.
  */
-static int tty_ldisc_wait_idle(struct tty_struct *tty)
+static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
 {
-       int ret;
+       long ret;
        ret = wait_event_timeout(tty_ldisc_idle,
-                       atomic_read(&tty->ldisc->users) == 1, 5 * HZ);
+                       atomic_read(&tty->ldisc->users) == 1, timeout);
        if (ret < 0)
                return ret;
        return ret > 0 ? 0 : -EBUSY;
@@ -665,7 +667,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
        tty_ldisc_flush_works(tty);
 
-       retval = tty_ldisc_wait_idle(tty);
+       retval = tty_ldisc_wait_idle(tty, 5 * HZ);
 
        tty_lock();
        mutex_lock(&tty->ldisc_mutex);
@@ -762,8 +764,6 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
        if (IS_ERR(ld))
                return -1;
 
-       WARN_ON_ONCE(tty_ldisc_wait_idle(tty));
-
        tty_ldisc_close(tty, tty->ldisc);
        tty_ldisc_put(tty->ldisc);
        tty->ldisc = NULL;
@@ -838,7 +838,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
        tty_unlock();
        cancel_work_sync(&tty->buf.work);
        mutex_unlock(&tty->ldisc_mutex);
-
+retry:
        tty_lock();
        mutex_lock(&tty->ldisc_mutex);
 
@@ -847,6 +847,22 @@ void tty_ldisc_hangup(struct tty_struct *tty)
           it means auditing a lot of other paths so this is
           a FIXME */
        if (tty->ldisc) {       /* Not yet closed */
+               if (atomic_read(&tty->ldisc->users) != 1) {
+                       char cur_n[TASK_COMM_LEN], tty_n[64];
+                       long timeout = 3 * HZ;
+                       tty_unlock();
+
+                       while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
+                               timeout = MAX_SCHEDULE_TIMEOUT;
+                               printk_ratelimited(KERN_WARNING
+                                       "%s: waiting (%s) for %s took too long, but we keep waiting...\n",
+                                       __func__, get_task_comm(cur_n, current),
+                                       tty_name(tty, tty_n));
+                       }
+                       mutex_unlock(&tty->ldisc_mutex);
+                       goto retry;
+               }
+
                if (reset == 0) {
 
                        if (!tty_ldisc_reinit(tty, tty->termios->c_line))
index 6960715c5063ce15d18ad1437af834bdb6be1c20..e8c564a533469f00f7e40435933ae496187aa20a 100644 (file)
@@ -539,7 +539,6 @@ static void acm_port_down(struct acm *acm)
 {
        int i;
 
-       mutex_lock(&open_mutex);
        if (acm->dev) {
                usb_autopm_get_interface(acm->control);
                acm_set_control(acm, acm->ctrlout = 0);
@@ -551,14 +550,15 @@ static void acm_port_down(struct acm *acm)
                acm->control->needs_remote_wakeup = 0;
                usb_autopm_put_interface(acm->control);
        }
-       mutex_unlock(&open_mutex);
 }
 
 static void acm_tty_hangup(struct tty_struct *tty)
 {
        struct acm *acm = tty->driver_data;
        tty_port_hangup(&acm->port);
+       mutex_lock(&open_mutex);
        acm_port_down(acm);
+       mutex_unlock(&open_mutex);
 }
 
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
@@ -569,8 +569,9 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
           shutdown */
        if (!acm)
                return;
+
+       mutex_lock(&open_mutex);
        if (tty_port_close_start(&acm->port, tty, filp) == 0) {
-               mutex_lock(&open_mutex);
                if (!acm->dev) {
                        tty_port_tty_set(&acm->port, NULL);
                        acm_tty_unregister(acm);
@@ -582,6 +583,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
        acm_port_down(acm);
        tty_port_close_end(&acm->port, tty);
        tty_port_tty_set(&acm->port, NULL);
+       mutex_unlock(&open_mutex);
 }
 
 static int acm_tty_write(struct tty_struct *tty,
index 96f05b29c9ad23ba6c0874a29dc2066c16806476..79781461eec97ad27c4986178266a63034f4693f 100644 (file)
@@ -813,6 +813,12 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                                        USB_PORT_FEAT_C_PORT_LINK_STATE);
                }
 
+               if ((portchange & USB_PORT_STAT_C_BH_RESET) &&
+                               hub_is_superspeed(hub->hdev)) {
+                       need_debounce_delay = true;
+                       clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_BH_PORT_RESET);
+               }
                /* We can forget about a "removed" device when there's a
                 * physical disconnect or the connect status changes.
                 */
index d6a8d8269bfbe6b68648d52068d846208aa9dd05..ecf12e15a7ef48a201c192dbc056b108c2416340 100644 (file)
@@ -50,15 +50,42 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Logitech Webcam B/C500 */
        { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech Webcam C600 */
+       { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Webcam Pro 9000 */
        { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech Webcam C905 */
+       { USB_DEVICE(0x046d, 0x080a), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Webcam C210 */
+       { USB_DEVICE(0x046d, 0x0819), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Webcam C260 */
+       { USB_DEVICE(0x046d, 0x081a), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Webcam C310 */
        { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech Webcam C910 */
+       { USB_DEVICE(0x046d, 0x0821), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Webcam C160 */
+       { USB_DEVICE(0x046d, 0x0824), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Webcam C270 */
        { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech Quickcam Pro 9000 */
+       { USB_DEVICE(0x046d, 0x0990), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Quickcam E3500 */
+       { USB_DEVICE(0x046d, 0x09a4), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Quickcam Vision Pro */
+       { USB_DEVICE(0x046d, 0x09a6), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Harmony 700-series */
        { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },
 
index fa824cfdd2eb42bf0869257303835a4305a16690..25dbd8614e7226ccf915bfa30817226a10272f3c 100644 (file)
@@ -1284,6 +1284,7 @@ static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc)
                        int             ret;
 
                        dep->endpoint.maxpacket = 1024;
+                       dep->endpoint.max_streams = 15;
                        dep->endpoint.ops = &dwc3_gadget_ep_ops;
                        list_add_tail(&dep->endpoint.ep_list,
                                        &dwc->gadget.ep_list);
index b21cd376c11af5978095c97f49bdee67aa1ec6d0..23a447373c51f0c7d3f9a08cadad7a90f217c24a 100644 (file)
@@ -469,7 +469,7 @@ config USB_LANGWELL
           gadget drivers to also be dynamically linked.
 
 config USB_EG20T
-       tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
+       tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
        depends on PCI
        select USB_GADGET_DUALSPEED
        help
@@ -485,10 +485,11 @@ config USB_EG20T
          This driver dose not support interrupt transfer or isochronous
          transfer modes.
 
-         This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is
+         This driver also can be used for LAPIS Semiconductor's ML7213 which is
          for IVI(In-Vehicle Infotainment) use.
-         ML7213 is companion chip for Intel Atom E6xx series.
-         ML7213 is completely compatible for Intel EG20T PCH.
+         ML7831 is for general purpose use.
+         ML7213/ML7831 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7831 is completely compatible for Intel EG20T PCH.
 
 config USB_CI13XXX_MSM
        tristate "MIPS USB CI13xxx for MSM"
index 4eedfe557154c285b9625d2117523ea3feef78ea..1fc612914c52e464ec89a82ec9e39048068c0b27 100644 (file)
@@ -122,3 +122,5 @@ static int __init ci13xxx_msm_init(void)
        return platform_driver_register(&ci13xxx_msm_driver);
 }
 module_init(ci13xxx_msm_init);
+
+MODULE_LICENSE("GPL v2");
index 83428f56253bd5283a8962448fa8cd7b899aee96..9a0c3979ff43faa2c54f05efa5fe8c76d8f23dff 100644 (file)
@@ -71,6 +71,9 @@
 /******************************************************************************
  * DEFINE
  *****************************************************************************/
+
+#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
+
 /* ctrl register bank access */
 static DEFINE_SPINLOCK(udc_lock);
 
@@ -1434,7 +1437,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
                return -EALREADY;
 
        mReq->req.status = -EALREADY;
-       if (length && !mReq->req.dma) {
+       if (length && mReq->req.dma == DMA_ADDR_INVALID) {
                mReq->req.dma = \
                        dma_map_single(mEp->device, mReq->req.buf,
                                       length, mEp->dir ? DMA_TO_DEVICE :
@@ -1453,7 +1456,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
                                dma_unmap_single(mEp->device, mReq->req.dma,
                                        length, mEp->dir ? DMA_TO_DEVICE :
                                        DMA_FROM_DEVICE);
-                               mReq->req.dma = 0;
+                               mReq->req.dma = DMA_ADDR_INVALID;
                                mReq->map     = 0;
                        }
                        return -ENOMEM;
@@ -1549,7 +1552,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
        if (mReq->map) {
                dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
                                 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               mReq->req.dma = 0;
+               mReq->req.dma = DMA_ADDR_INVALID;
                mReq->map     = 0;
        }
 
@@ -1610,7 +1613,6 @@ __acquires(mEp->lock)
  * @gadget: gadget
  *
  * This function returns an error code
- * Caller must hold lock
  */
 static int _gadget_stop_activity(struct usb_gadget *gadget)
 {
@@ -2189,6 +2191,7 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
        mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
        if (mReq != NULL) {
                INIT_LIST_HEAD(&mReq->queue);
+               mReq->req.dma = DMA_ADDR_INVALID;
 
                mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
                                           &mReq->dma);
@@ -2328,7 +2331,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
        if (mReq->map) {
                dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
                                 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               mReq->req.dma = 0;
+               mReq->req.dma = DMA_ADDR_INVALID;
                mReq->map     = 0;
        }
        req->status = -ECONNRESET;
@@ -2500,12 +2503,12 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)
        spin_lock_irqsave(udc->lock, flags);
        if (!udc->remote_wakeup) {
                ret = -EOPNOTSUPP;
-               dbg_trace("remote wakeup feature is not enabled\n");
+               trace("remote wakeup feature is not enabled\n");
                goto out;
        }
        if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
                ret = -EINVAL;
-               dbg_trace("port is not suspended\n");
+               trace("port is not suspended\n");
                goto out;
        }
        hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
@@ -2703,7 +2706,9 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)
                if (udc->udc_driver->notify_event)
                        udc->udc_driver->notify_event(udc,
                        CI13XXX_CONTROLLER_STOPPED_EVENT);
+               spin_unlock_irqrestore(udc->lock, flags);
                _gadget_stop_activity(&udc->gadget);
+               spin_lock_irqsave(udc->lock, flags);
                pm_runtime_put(&udc->gadget.dev);
        }
 
@@ -2850,7 +2855,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
        struct ci13xxx *udc;
        int retval = 0;
 
-       trace("%p, %p, %p", dev, regs, name);
+       trace("%p, %p, %p", dev, regs, driver->name);
 
        if (dev == NULL || regs == NULL || driver == NULL ||
                        driver->name == NULL)
index 52583a2353304acb25119365a5432c916e0aeb73..c39d58860fa0414a2c862941dbc4382ddb2e1b0f 100644 (file)
@@ -624,7 +624,8 @@ static int fsg_setup(struct usb_function *f,
                if (ctrl->bRequestType !=
                    (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
                        break;
-               if (w_index != fsg->interface_number || w_value != 0)
+               if (w_index != fsg->interface_number || w_value != 0 ||
+                               w_length != 0)
                        return -EDOM;
 
                /*
@@ -639,7 +640,8 @@ static int fsg_setup(struct usb_function *f,
                if (ctrl->bRequestType !=
                    (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
                        break;
-               if (w_index != fsg->interface_number || w_value != 0)
+               if (w_index != fsg->interface_number || w_value != 0 ||
+                               w_length != 1)
                        return -EDOM;
                VDBG(fsg, "get max LUN\n");
                *(u8 *)req->buf = fsg->common->nluns - 1;
index 67b222908cf9fe264a3213b945f0beae5fa83569..3797b3d6c622bd49ff709b33303a86e323294c44 100644 (file)
@@ -95,7 +95,6 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req);
 
 DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
 DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
-DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(16);
 DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
 
 /* B.3.1  Standard AC Interface Descriptor */
@@ -140,26 +139,6 @@ static struct usb_ms_header_descriptor ms_header_desc __initdata = {
        /* .wTotalLength =      DYNAMIC */
 };
 
-/* B.4.3  Embedded MIDI IN Jack Descriptor */
-static struct usb_midi_in_jack_descriptor jack_in_emb_desc = {
-       .bLength =            USB_DT_MIDI_IN_SIZE,
-       .bDescriptorType =      USB_DT_CS_INTERFACE,
-       .bDescriptorSubtype =   USB_MS_MIDI_IN_JACK,
-       .bJackType =        USB_MS_EMBEDDED,
-       /* .bJackID =           DYNAMIC */
-};
-
-/* B.4.4  Embedded MIDI OUT Jack Descriptor */
-static struct usb_midi_out_jack_descriptor_16 jack_out_emb_desc = {
-       /* .bLength =           DYNAMIC */
-       .bDescriptorType =      USB_DT_CS_INTERFACE,
-       .bDescriptorSubtype =   USB_MS_MIDI_OUT_JACK,
-       .bJackType =            USB_MS_EMBEDDED,
-       /* .bJackID =           DYNAMIC */
-       /* .bNrInputPins =      DYNAMIC */
-       /* .pins =              DYNAMIC */
-};
-
 /* B.5.1  Standard Bulk OUT Endpoint Descriptor */
 static struct usb_endpoint_descriptor bulk_out_desc = {
        .bLength =              USB_DT_ENDPOINT_AUDIO_SIZE,
@@ -758,9 +737,11 @@ fail:
 static int __init
 f_midi_bind(struct usb_configuration *c, struct usb_function *f)
 {
-       struct usb_descriptor_header *midi_function[(MAX_PORTS * 2) + 12];
+       struct usb_descriptor_header **midi_function;
        struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
+       struct usb_midi_in_jack_descriptor jack_in_emb_desc[MAX_PORTS];
        struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS];
+       struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS];
        struct usb_composite_dev *cdev = c->cdev;
        struct f_midi *midi = func_to_midi(f);
        int status, n, jack = 1, i = 0;
@@ -798,6 +779,14 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
                goto fail;
        midi->out_ep->driver_data = cdev;       /* claim */
 
+       /* allocate temporary function list */
+       midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(midi_function),
+                               GFP_KERNEL);
+       if (!midi_function) {
+               status = -ENOMEM;
+               goto fail;
+       }
+
        /*
         * construct the function's descriptor set. As the number of
         * input and output MIDI ports is configurable, we have to do
@@ -811,73 +800,74 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
 
        /* calculate the header's wTotalLength */
        n = USB_DT_MS_HEADER_SIZE
-               + (1 + midi->in_ports) * USB_DT_MIDI_IN_SIZE
-               + (1 + midi->out_ports) * USB_DT_MIDI_OUT_SIZE(1);
+               + (midi->in_ports + midi->out_ports) *
+                       (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1));
        ms_header_desc.wTotalLength = cpu_to_le16(n);
 
        midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc;
 
-       /* we have one embedded IN jack */
-       jack_in_emb_desc.bJackID = jack++;
-       midi_function[i++] = (struct usb_descriptor_header *) &jack_in_emb_desc;
-
-       /* and a dynamic amount of external IN jacks */
-       for (n = 0; n < midi->in_ports; n++) {
-               struct usb_midi_in_jack_descriptor *ext = &jack_in_ext_desc[n];
-
-               ext->bLength =                  USB_DT_MIDI_IN_SIZE;
-               ext->bDescriptorType =          USB_DT_CS_INTERFACE;
-               ext->bDescriptorSubtype =       USB_MS_MIDI_IN_JACK;
-               ext->bJackType =                USB_MS_EXTERNAL;
-               ext->bJackID =                  jack++;
-               ext->iJack =                    0;
-
-               midi_function[i++] = (struct usb_descriptor_header *) ext;
-       }
-
-       /* one embedded OUT jack ... */
-       jack_out_emb_desc.bLength = USB_DT_MIDI_OUT_SIZE(midi->in_ports);
-       jack_out_emb_desc.bJackID = jack++;
-       jack_out_emb_desc.bNrInputPins = midi->in_ports;
-       /* ... which referencess all external IN jacks */
+       /* configure the external IN jacks, each linked to an embedded OUT jack */
        for (n = 0; n < midi->in_ports; n++) {
-               jack_out_emb_desc.pins[n].baSourceID = jack_in_ext_desc[n].bJackID;
-               jack_out_emb_desc.pins[n].baSourcePin = 1;
+               struct usb_midi_in_jack_descriptor *in_ext = &jack_in_ext_desc[n];
+               struct usb_midi_out_jack_descriptor_1 *out_emb = &jack_out_emb_desc[n];
+
+               in_ext->bLength                 = USB_DT_MIDI_IN_SIZE;
+               in_ext->bDescriptorType         = USB_DT_CS_INTERFACE;
+               in_ext->bDescriptorSubtype      = USB_MS_MIDI_IN_JACK;
+               in_ext->bJackType               = USB_MS_EXTERNAL;
+               in_ext->bJackID                 = jack++;
+               in_ext->iJack                   = 0;
+               midi_function[i++] = (struct usb_descriptor_header *) in_ext;
+
+               out_emb->bLength                = USB_DT_MIDI_OUT_SIZE(1);
+               out_emb->bDescriptorType        = USB_DT_CS_INTERFACE;
+               out_emb->bDescriptorSubtype     = USB_MS_MIDI_OUT_JACK;
+               out_emb->bJackType              = USB_MS_EMBEDDED;
+               out_emb->bJackID                = jack++;
+               out_emb->bNrInputPins           = 1;
+               out_emb->pins[0].baSourcePin    = 1;
+               out_emb->pins[0].baSourceID     = in_ext->bJackID;
+               out_emb->iJack                  = 0;
+               midi_function[i++] = (struct usb_descriptor_header *) out_emb;
+
+               /* link it to the endpoint */
+               ms_in_desc.baAssocJackID[n] = out_emb->bJackID;
        }
 
-       midi_function[i++] = (struct usb_descriptor_header *) &jack_out_emb_desc;
-
-       /* and multiple external OUT jacks ... */
+       /* configure the external OUT jacks, each linked to an embedded IN jack */
        for (n = 0; n < midi->out_ports; n++) {
-               struct usb_midi_out_jack_descriptor_1 *ext = &jack_out_ext_desc[n];
-               int m;
-
-               ext->bLength =                  USB_DT_MIDI_OUT_SIZE(1);
-               ext->bDescriptorType =          USB_DT_CS_INTERFACE;
-               ext->bDescriptorSubtype =       USB_MS_MIDI_OUT_JACK;
-               ext->bJackType =                USB_MS_EXTERNAL;
-               ext->bJackID =                  jack++;
-               ext->bNrInputPins =             1;
-               ext->iJack =                    0;
-               /* ... which all reference the same embedded IN jack */
-               for (m = 0; m < midi->out_ports; m++) {
-                       ext->pins[m].baSourceID =       jack_in_emb_desc.bJackID;
-                       ext->pins[m].baSourcePin =      1;
-               }
-
-               midi_function[i++] = (struct usb_descriptor_header *) ext;
+               struct usb_midi_in_jack_descriptor *in_emb = &jack_in_emb_desc[n];
+               struct usb_midi_out_jack_descriptor_1 *out_ext = &jack_out_ext_desc[n];
+
+               in_emb->bLength                 = USB_DT_MIDI_IN_SIZE;
+               in_emb->bDescriptorType         = USB_DT_CS_INTERFACE;
+               in_emb->bDescriptorSubtype      = USB_MS_MIDI_IN_JACK;
+               in_emb->bJackType               = USB_MS_EMBEDDED;
+               in_emb->bJackID                 = jack++;
+               in_emb->iJack                   = 0;
+               midi_function[i++] = (struct usb_descriptor_header *) in_emb;
+
+               out_ext->bLength =              USB_DT_MIDI_OUT_SIZE(1);
+               out_ext->bDescriptorType =      USB_DT_CS_INTERFACE;
+               out_ext->bDescriptorSubtype =   USB_MS_MIDI_OUT_JACK;
+               out_ext->bJackType =            USB_MS_EXTERNAL;
+               out_ext->bJackID =              jack++;
+               out_ext->bNrInputPins =         1;
+               out_ext->iJack =                0;
+               out_ext->pins[0].baSourceID =   in_emb->bJackID;
+               out_ext->pins[0].baSourcePin =  1;
+               midi_function[i++] = (struct usb_descriptor_header *) out_ext;
+
+               /* link it to the endpoint */
+               ms_out_desc.baAssocJackID[n] = in_emb->bJackID;
        }
 
        /* configure the endpoint descriptors ... */
        ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports);
        ms_out_desc.bNumEmbMIDIJack = midi->in_ports;
-       for (n = 0; n < midi->in_ports; n++)
-               ms_out_desc.baAssocJackID[n] = jack_in_emb_desc.bJackID;
 
        ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports);
        ms_in_desc.bNumEmbMIDIJack = midi->out_ports;
-       for (n = 0; n < midi->out_ports; n++)
-               ms_in_desc.baAssocJackID[n] = jack_out_emb_desc.bJackID;
 
        /* ... and add them to the list */
        midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc;
@@ -901,6 +891,8 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
                f->descriptors = usb_copy_descriptors(midi_function);
        }
 
+       kfree(midi_function);
+
        return 0;
 
 fail:
index 3490770333383d3d63c08977901b9311ff7cef15..16a509ae517b6b5a317422aa2553ce1316da46c5 100644 (file)
@@ -346,7 +346,7 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
                }
 
                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
-                               skb->len == 0, req->actual);
+                               skb->len <= 1, req->actual);
                page = NULL;
 
                if (req->actual < req->length) { /* Last fragment */
index f7e39b0365cee5de76bc66d1942eeb2e322d6123..11b5196284aed6253180b699094cd7b6dbc762ea 100644 (file)
@@ -859,7 +859,7 @@ static int class_setup_req(struct fsg_dev *fsg,
                        if (ctrl->bRequestType != (USB_DIR_OUT |
                                        USB_TYPE_CLASS | USB_RECIP_INTERFACE))
                                break;
-                       if (w_index != 0 || w_value != 0) {
+                       if (w_index != 0 || w_value != 0 || w_length != 0) {
                                value = -EDOM;
                                break;
                        }
@@ -875,7 +875,7 @@ static int class_setup_req(struct fsg_dev *fsg,
                        if (ctrl->bRequestType != (USB_DIR_IN |
                                        USB_TYPE_CLASS | USB_RECIP_INTERFACE))
                                break;
-                       if (w_index != 0 || w_value != 0) {
+                       if (w_index != 0 || w_value != 0 || w_length != 1) {
                                value = -EDOM;
                                break;
                        }
index b2c44e1d58134c185966e672508ec0a9f8d24d84..b3b3d83b7c3354744ec1fc4d4dc2765f19293a7c 100644 (file)
@@ -1717,7 +1717,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
 
 static inline enum usb_device_speed portscx_device_speed(u32 reg)
 {
-       switch (speed & PORTSCX_PORT_SPEED_MASK) {
+       switch (reg & PORTSCX_PORT_SPEED_MASK) {
        case PORTSCX_PORT_SPEED_HIGH:
                return USB_SPEED_HIGH;
        case PORTSCX_PORT_SPEED_FULL:
@@ -2480,8 +2480,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 #ifndef CONFIG_ARCH_MXC
        if (pdata->have_sysif_regs)
-               usb_sys_regs = (struct usb_sys_interface *)
-                               ((u32)dr_regs + USB_DR_SYS_OFFSET);
+               usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET;
 #endif
 
        /* Initialize USB clocks */
index a392ec0d2d5179beebf3923dc6b275001b4961c5..6ccae2707e596c3f24d5705495264f0dcfa4f31b 100644 (file)
@@ -1730,8 +1730,9 @@ static void
 gadgetfs_disconnect (struct usb_gadget *gadget)
 {
        struct dev_data         *dev = get_gadget_data (gadget);
+       unsigned long           flags;
 
-       spin_lock (&dev->lock);
+       spin_lock_irqsave (&dev->lock, flags);
        if (dev->state == STATE_DEV_UNCONNECTED)
                goto exit;
        dev->state = STATE_DEV_UNCONNECTED;
@@ -1740,7 +1741,7 @@ gadgetfs_disconnect (struct usb_gadget *gadget)
        next_event (dev, GADGETFS_DISCONNECT);
        ep0_readable (dev);
 exit:
-       spin_unlock (&dev->lock);
+       spin_unlock_irqrestore (&dev->lock, flags);
 }
 
 static void
index 550d6dcdf10454253cdb3d93f6a7d86219ce4a50..5048a0c07640a4ed649c848a43ae4b83c5298be4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -354,6 +354,7 @@ struct pch_udc_dev {
 #define PCI_DEVICE_ID_INTEL_EG20T_UDC  0x8808
 #define PCI_VENDOR_ID_ROHM             0x10DB
 #define PCI_DEVICE_ID_ML7213_IOH_UDC   0x801D
+#define PCI_DEVICE_ID_ML7831_IOH_UDC   0x8808
 
 static const char      ep0_string[] = "ep0in";
 static DEFINE_SPINLOCK(udc_stall_spinlock);    /* stall spin lock */
@@ -2970,6 +2971,11 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
                .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
                .class_mask = 0xffffffff,
        },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7831_IOH_UDC),
+               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class_mask = 0xffffffff,
+       },
        { 0 },
 };
 
@@ -2999,5 +3005,5 @@ static void __exit pch_udc_pci_exit(void)
 module_exit(pch_udc_pci_exit);
 
 MODULE_DESCRIPTION("Intel EG20T USB Device Controller");
-MODULE_AUTHOR("OKI SEMICONDUCTOR, <toshiharu-linux@dsn.okisemi.com>");
+MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>");
 MODULE_LICENSE("GPL");
index 68a826a1b866e8a9191711da9c5e0da40eaf2e22..24f84b210ce116cfd78e5bae3a1bee383d198ca0 100644 (file)
@@ -1718,6 +1718,8 @@ static void r8a66597_fifo_flush(struct usb_ep *_ep)
        if (list_empty(&ep->queue) && !ep->busy) {
                pipe_stop(ep->r8a66597, ep->pipenum);
                r8a66597_bclr(ep->r8a66597, BCLR, ep->fifoctr);
+               r8a66597_write(ep->r8a66597, ACLRM, ep->pipectr);
+               r8a66597_write(ep->r8a66597, 0, ep->pipectr);
        }
        spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
 }
@@ -1742,7 +1744,6 @@ static int r8a66597_start(struct usb_gadget *gadget,
                struct usb_gadget_driver *driver)
 {
        struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
-       int retval;
 
        if (!driver
                        || driver->speed != USB_SPEED_HIGH
@@ -1752,16 +1753,7 @@ static int r8a66597_start(struct usb_gadget *gadget,
                return -ENODEV;
 
        /* hook up the driver */
-       driver->driver.bus = NULL;
        r8a66597->driver = driver;
-       r8a66597->gadget.dev.driver = &driver->driver;
-
-       retval = device_add(&r8a66597->gadget.dev);
-       if (retval) {
-               dev_err(r8a66597_to_dev(r8a66597), "device_add error (%d)\n",
-                       retval);
-               goto error;
-       }
 
        init_controller(r8a66597);
        r8a66597_bset(r8a66597, VBSE, INTENB0);
@@ -1775,12 +1767,6 @@ static int r8a66597_start(struct usb_gadget *gadget,
        }
 
        return 0;
-
-error:
-       r8a66597->driver = NULL;
-       r8a66597->gadget.dev.driver = NULL;
-
-       return retval;
 }
 
 static int r8a66597_stop(struct usb_gadget *gadget,
@@ -1794,7 +1780,6 @@ static int r8a66597_stop(struct usb_gadget *gadget,
        disable_controller(r8a66597);
        spin_unlock_irqrestore(&r8a66597->lock, flags);
 
-       device_del(&r8a66597->gadget.dev);
        r8a66597->driver = NULL;
        return 0;
 }
@@ -1845,6 +1830,7 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
                clk_put(r8a66597->clk);
        }
 #endif
+       device_unregister(&r8a66597->gadget.dev);
        kfree(r8a66597);
        return 0;
 }
@@ -1924,13 +1910,17 @@ static int __init r8a66597_probe(struct platform_device *pdev)
        r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
        r8a66597->gadget.ops = &r8a66597_gadget_ops;
-       device_initialize(&r8a66597->gadget.dev);
        dev_set_name(&r8a66597->gadget.dev, "gadget");
        r8a66597->gadget.is_dualspeed = 1;
        r8a66597->gadget.dev.parent = &pdev->dev;
        r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
        r8a66597->gadget.dev.release = pdev->dev.release;
        r8a66597->gadget.name = udc_name;
+       ret = device_register(&r8a66597->gadget.dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "device_register failed\n");
+               goto clean_up;
+       }
 
        init_timer(&r8a66597->timer);
        r8a66597->timer.function = r8a66597_timer;
@@ -1945,7 +1935,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
                                clk_name);
                        ret = PTR_ERR(r8a66597->clk);
-                       goto clean_up;
+                       goto clean_up_dev;
                }
                clk_enable(r8a66597->clk);
        }
@@ -2014,7 +2004,9 @@ clean_up2:
                clk_disable(r8a66597->clk);
                clk_put(r8a66597->clk);
        }
+clean_up_dev:
 #endif
+       device_unregister(&r8a66597->gadget.dev);
 clean_up:
        if (r8a66597) {
                if (r8a66597->sudmac_reg)
index 022baeca7c94f4f55819d6cf2be5550752e3318a..6939e17f4580099af82d236c413547fe3660a18d 100644 (file)
@@ -210,10 +210,10 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 
        if (udc_is_newstyle(udc)) {
-               usb_gadget_disconnect(udc->gadget);
+               udc->driver->disconnect(udc->gadget);
                udc->driver->unbind(udc->gadget);
                usb_gadget_udc_stop(udc->gadget, udc->driver);
-
+               usb_gadget_disconnect(udc->gadget);
        } else {
                usb_gadget_stop(udc->gadget, udc->driver);
        }
@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
 static ssize_t usb_udc_srp_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t n)
 {
-       struct usb_udc          *udc = dev_get_drvdata(dev);
+       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
 
        if (sysfs_streq(buf, "1"))
                usb_gadget_wakeup(udc->gadget);
@@ -378,7 +378,7 @@ static ssize_t usb_udc_speed_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        usb_speed_string(udc->gadget->speed));
 }
-static DEVICE_ATTR(speed, S_IRUSR, usb_udc_speed_show, NULL);
+static DEVICE_ATTR(speed, S_IRUGO, usb_udc_speed_show, NULL);
 
 #define USB_UDC_ATTR(name)                                     \
 ssize_t usb_udc_##name##_show(struct device *dev,              \
@@ -389,7 +389,7 @@ ssize_t usb_udc_##name##_show(struct device *dev,           \
                                                                \
        return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name);  \
 }                                                              \
-static DEVICE_ATTR(name, S_IRUSR, usb_udc_##name##_show, NULL)
+static DEVICE_ATTR(name, S_IRUGO, usb_udc_##name##_show, NULL)
 
 static USB_UDC_ATTR(is_dualspeed);
 static USB_UDC_ATTR(is_otg);
index 2e829fae648291d1fc885653e274b7e891d4e09e..56a32033adb3485db49484d23619d1f2dcf68071 100644 (file)
@@ -1479,10 +1479,15 @@ iso_stream_schedule (
 
                /* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
 
-               /* find a uframe slot with enough bandwidth */
-               next = start + period;
-               for (; start < next; start++) {
-
+               /* find a uframe slot with enough bandwidth.
+                * Early uframes are more precious because full-speed
+                * iso IN transfers can't use late uframes,
+                * and therefore they should be allocated last.
+                */
+               next = start;
+               start += period;
+               do {
+                       start--;
                        /* check schedule: enough space? */
                        if (stream->highspeed) {
                                if (itd_slot_ok(ehci, mod, start,
@@ -1495,7 +1500,7 @@ iso_stream_schedule (
                                                start, sched, period))
                                        break;
                        }
-               }
+               } while (start > next);
 
                /* no room in the schedule */
                if (start == next) {
index fe74bd6760187c221e79dae448005c07a25863be..b4fb511d24bcda76a4101aa605e01384c5962d21 100644 (file)
@@ -19,7 +19,7 @@ static int ehci_xls_setup(struct usb_hcd *hcd)
 
        ehci->caps = hcd->regs;
        ehci->regs = hcd->regs +
-               HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+               HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
        dbg_hcs_params(ehci, "reset");
        dbg_hcc_params(ehci, "reset");
 
index ba3a46b78b75a7bd16e54e7e9d3690dd5f9df4ef..95a9fec38e89b4e8a6daff8a3c0c75fd73315d4c 100644 (file)
@@ -223,6 +223,9 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int
        if (port < 0 || port >= 2)
                return;
 
+       if (pdata->vbus_pin[port] <= 0)
+               return;
+
        gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable);
 }
 
@@ -231,6 +234,9 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
        if (port < 0 || port >= 2)
                return -EINVAL;
 
+       if (pdata->vbus_pin[port] <= 0)
+               return -EINVAL;
+
        return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted;
 }
 
index 34efd479e068cbd8133fbd98f8c2a2cd47efa862..b2639191549e88172e803281a6c53300bd103b67 100644 (file)
@@ -389,17 +389,14 @@ ohci_shutdown (struct usb_hcd *hcd)
        struct ohci_hcd *ohci;
 
        ohci = hcd_to_ohci (hcd);
-       ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+       ohci_writel(ohci, (u32) ~0, &ohci->regs->intrdisable);
 
-       /* If the SHUTDOWN quirk is set, don't put the controller in RESET */
-       ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
-                       OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
-                       OHCI_CTRL_RWC);
-       ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
+       /* Software reset, after which the controller goes into SUSPEND */
+       ohci_writel(ohci, OHCI_HCR, &ohci->regs->cmdstatus);
+       ohci_readl(ohci, &ohci->regs->cmdstatus);       /* flush the writes */
+       udelay(10);
 
-       /* flush the writes */
-       (void) ohci_readl (ohci, &ohci->regs->control);
+       ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval);
 }
 
 static int check_ed(struct ohci_hcd *ohci, struct ed *ed)
index ad8166c681e2894424b81850aa3a366108d8d11c..bc01b064585ac9da1d232106586d71937b78db66 100644 (file)
@@ -175,28 +175,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
        return 0;
 }
 
-/* nVidia controllers continue to drive Reset signalling on the bus
- * even after system shutdown, wasting power.  This flag tells the
- * shutdown routine to leave the controller OPERATIONAL instead of RESET.
- */
-static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
-{
-       struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-       /* Evidently nVidia fixed their later hardware; this is a guess at
-        * the changeover point.
-        */
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB          0x026d
-
-       if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
-               ohci->flags |= OHCI_QUIRK_SHUTDOWN;
-               ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
-       }
-
-       return 0;
-}
-
 static void sb800_prefetch(struct ohci_hcd *ohci, int on)
 {
        struct pci_dev *pdev;
@@ -260,10 +238,6 @@ static const struct pci_device_id ohci_pci_quirks[] = {
                PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
                .driver_data = (unsigned long)ohci_quirk_amd700,
        },
-       {
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
-               .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
-       },
 
        /* FIXME for some of the early AMD 760 southbridges, OHCI
         * won't work at all.  blacklist them.
index 35e5fd640ce75388c7f373544c62e965f34c0111..0795b934d00c9709800948c137a1aa84fd96e47d 100644 (file)
@@ -403,7 +403,6 @@ struct ohci_hcd {
 #define        OHCI_QUIRK_HUB_POWER    0x100                   /* distrust firmware power/oc setup */
 #define        OHCI_QUIRK_AMD_PLL      0x200                   /* AMD PLL quirk*/
 #define        OHCI_QUIRK_AMD_PREFETCH 0x400                   /* pre-fetch for ISO transfer */
-#define        OHCI_QUIRK_SHUTDOWN     0x800                   /* nVidia power bug */
        // there are also chip quirks/bugs in init logic
 
        struct work_struct      nec_work;       /* Worker for NEC quirk */
index 27a3dec32fa2f78895175f32a89f5e8f0270f7cc..caf87428ca43c3f38985d9469b566645ea3d3bf9 100644 (file)
@@ -37,6 +37,7 @@
 #define OHCI_INTRENABLE                0x10
 #define OHCI_INTRDISABLE       0x14
 #define OHCI_FMINTERVAL                0x34
+#define OHCI_HCFS              (3 << 6)        /* hc functional state */
 #define OHCI_HCR               (1 << 0)        /* host controller reset */
 #define OHCI_OCR               (1 << 3)        /* ownership change request */
 #define OHCI_CTRL_RWC          (1 << 9)        /* remote wakeup connected */
@@ -466,6 +467,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 {
        void __iomem *base;
        u32 control;
+       u32 fminterval;
+       int cnt;
 
        if (!mmio_resource_enabled(pdev, 0))
                return;
@@ -498,41 +501,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
        }
 #endif
 
-       /* reset controller, preserving RWC (and possibly IR) */
-       writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
-       readl(base + OHCI_CONTROL);
+       /* disable interrupts */
+       writel((u32) ~0, base + OHCI_INTRDISABLE);
 
-       /* Some NVIDIA controllers stop working if kept in RESET for too long */
-       if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
-               u32 fminterval;
-               int cnt;
+       /* Reset the USB bus, if the controller isn't already in RESET */
+       if (control & OHCI_HCFS) {
+               /* Go into RESET, preserving RWC (and possibly IR) */
+               writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+               readl(base + OHCI_CONTROL);
 
-               /* drive reset for at least 50 ms (7.1.7.5) */
+               /* drive bus reset for at least 50 ms (7.1.7.5) */
                msleep(50);
+       }
 
-               /* software reset of the controller, preserving HcFmInterval */
-               fminterval = readl(base + OHCI_FMINTERVAL);
-               writel(OHCI_HCR, base + OHCI_CMDSTATUS);
+       /* software reset of the controller, preserving HcFmInterval */
+       fminterval = readl(base + OHCI_FMINTERVAL);
+       writel(OHCI_HCR, base + OHCI_CMDSTATUS);
 
-               /* reset requires max 10 us delay */
-               for (cnt = 30; cnt > 0; --cnt) {        /* ... allow extra time */
-                       if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
-                               break;
-                       udelay(1);
-               }
-               writel(fminterval, base + OHCI_FMINTERVAL);
-
-               /* Now we're in the SUSPEND state with all devices reset
-                * and wakeups and interrupts disabled
-                */
+       /* reset requires max 10 us delay */
+       for (cnt = 30; cnt > 0; --cnt) {        /* ... allow extra time */
+               if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
+                       break;
+               udelay(1);
        }
+       writel(fminterval, base + OHCI_FMINTERVAL);
 
-       /*
-        * disable interrupts
-        */
-       writel(~(u32)0, base + OHCI_INTRDISABLE);
-       writel(~(u32)0, base + OHCI_INTRSTATUS);
-
+       /* Now the controller is safely in SUSPEND and nothing can wake it up */
        iounmap(base);
 }
 
@@ -627,7 +621,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
        void __iomem *base, *op_reg_base;
        u32     hcc_params, cap, val;
        u8      offset, cap_length;
-       int     wait_time, delta, count = 256/4;
+       int     wait_time, count = 256/4;
 
        if (!mmio_resource_enabled(pdev, 0))
                return;
@@ -673,11 +667,10 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
                writel(val, op_reg_base + EHCI_USBCMD);
 
                wait_time = 2000;
-               delta = 100;
                do {
                        writel(0x3f, op_reg_base + EHCI_USBSTS);
-                       udelay(delta);
-                       wait_time -= delta;
+                       udelay(100);
+                       wait_time -= 100;
                        val = readl(op_reg_base + EHCI_USBSTS);
                        if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
                                break;
index 42a22b8e692262fde4eab6b2133fc6cf485555a7..0e4b25fa3bcd262a898d6337aeeb9b6cec7b5600 100644 (file)
@@ -982,7 +982,6 @@ 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 xhci_slot_ctx    *slot_ctx;
-       struct xhci_input_control_ctx *ctrl_ctx;
        u32                     port_num;
        struct usb_device *top_dev;
 
@@ -994,12 +993,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
                return -EINVAL;
        }
        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*/
-       ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
-
        /* 3) Only the control endpoint is valid - one endpoint context */
        slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);
        switch (udev->speed) {
index 940321b3ec68b477549a38d4016ee047fb7a72a7..9f1d4b15d818553fc488c8651a14d0e4b3301f66 100644 (file)
@@ -816,23 +816,24 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
        struct xhci_ring *ring;
        struct xhci_td *cur_td;
        int ret, i, j;
+       unsigned long flags;
 
        ep = (struct xhci_virt_ep *) arg;
        xhci = ep->xhci;
 
-       spin_lock(&xhci->lock);
+       spin_lock_irqsave(&xhci->lock, flags);
 
        ep->stop_cmds_pending--;
        if (xhci->xhc_state & XHCI_STATE_DYING) {
                xhci_dbg(xhci, "Stop EP timer ran, but another timer marked "
                                "xHCI as DYING, exiting.\n");
-               spin_unlock(&xhci->lock);
+               spin_unlock_irqrestore(&xhci->lock, flags);
                return;
        }
        if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {
                xhci_dbg(xhci, "Stop EP timer ran, but no command pending, "
                                "exiting.\n");
-               spin_unlock(&xhci->lock);
+               spin_unlock_irqrestore(&xhci->lock, flags);
                return;
        }
 
@@ -844,11 +845,11 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
        xhci->xhc_state |= XHCI_STATE_DYING;
        /* Disable interrupts from the host controller and start halting it */
        xhci_quiesce(xhci);
-       spin_unlock(&xhci->lock);
+       spin_unlock_irqrestore(&xhci->lock, flags);
 
        ret = xhci_halt(xhci);
 
-       spin_lock(&xhci->lock);
+       spin_lock_irqsave(&xhci->lock, flags);
        if (ret < 0) {
                /* This is bad; the host is not responding to commands and it's
                 * not allowing itself to be halted.  At least interrupts are
@@ -896,7 +897,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
                        }
                }
        }
-       spin_unlock(&xhci->lock);
+       spin_unlock_irqrestore(&xhci->lock, flags);
        xhci_dbg(xhci, "Calling usb_hc_died()\n");
        usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
        xhci_dbg(xhci, "xHCI host controller is dead.\n");
index 1ff95a0df576762000796440a9b82aae53832718..aa94c01957919001e6a5804c7bc0434b923f20bc 100644 (file)
@@ -799,7 +799,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
        u32                     command, temp = 0;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        struct usb_hcd          *secondary_hcd;
-       int                     retval;
+       int                     retval = 0;
 
        /* Wait a bit if either of the roothubs need to settle from the
         * transition into bus suspend.
@@ -809,6 +809,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                                xhci->bus_state[1].next_statechange))
                msleep(100);
 
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
+
        spin_lock_irq(&xhci->lock);
        if (xhci->quirks & XHCI_RESET_ON_RESUME)
                hibernated = true;
@@ -878,20 +881,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                        return retval;
                xhci_dbg(xhci, "Start the primary HCD\n");
                retval = xhci_run(hcd->primary_hcd);
-               if (retval)
-                       goto failed_restart;
-
-               xhci_dbg(xhci, "Start the secondary HCD\n");
-               retval = xhci_run(secondary_hcd);
                if (!retval) {
-                       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-                       set_bit(HCD_FLAG_HW_ACCESSIBLE,
-                                       &xhci->shared_hcd->flags);
+                       xhci_dbg(xhci, "Start the secondary HCD\n");
+                       retval = xhci_run(secondary_hcd);
                }
-failed_restart:
                hcd->state = HC_STATE_SUSPENDED;
                xhci->shared_hcd->state = HC_STATE_SUSPENDED;
-               return retval;
+               goto done;
        }
 
        /* step 4: set Run/Stop bit */
@@ -910,11 +906,14 @@ failed_restart:
         * Running endpoints by ringing their doorbells
         */
 
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
-
        spin_unlock_irq(&xhci->lock);
-       return 0;
+
+ done:
+       if (retval == 0) {
+               usb_hcd_resume_root_hub(hcd);
+               usb_hcd_resume_root_hub(xhci->shared_hcd);
+       }
+       return retval;
 }
 #endif /* CONFIG_PM */
 
@@ -3504,6 +3503,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
        /* Otherwise, update the control endpoint ring enqueue pointer. */
        else
                xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
+       ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
+       ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
+       ctrl_ctx->drop_flags = 0;
+
        xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
        xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
 
@@ -3585,7 +3588,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
        virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
                + 1;
        /* Zero the input context control for later use */
-       ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
        ctrl_ctx->add_flags = 0;
        ctrl_ctx->drop_flags = 0;
 
index fc34b8b1191055bcb568a171a518d389b4266f25..07a03460a598c3bcea675494a2a9009312b5d57b 100644 (file)
@@ -11,6 +11,7 @@ config USB_MUSB_HDRC
        select TWL4030_USB if MACH_OMAP_3430SDP
        select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
        select USB_OTG_UTILS
+       select USB_GADGET_DUALSPEED
        tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
        help
          Say Y here if your system has a dual role high speed USB
@@ -60,7 +61,7 @@ config USB_MUSB_BLACKFIN
 
 config USB_MUSB_UX500
        tristate "U8500 and U5500"
-       depends on (ARCH_U8500 && AB8500_USB) || (ARCH_U5500)
+       depends on (ARCH_U8500 && AB8500_USB)
 
 endchoice
 
index 08f1d0b662a37b64558e70777bf13f609da1bb47..e233d2b7d335713a3af128258f8634014aa3c5fe 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
index 4da7492ddbdba25768f4acbce91c1802195f48da..2613bfdb09b65da2ecb274edbf160b237bfde066 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
index 20a28731c338e8aa9dbf2bac295ce8ddda426e3a..c1fa12ec7a9ad456a23c761f5c328a721182a070 100644 (file)
@@ -1477,8 +1477,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
-       defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) || \
-       defined(CONFIG_ARCH_U5500)
+       defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
 
 static irqreturn_t generic_interrupt(int irq, void *__hci)
 {
index ae4a20acef6c6e1265f2666d00c09cdee4d19032..d51043acfe1abc5013217e70b4854e153f8bdf96 100644 (file)
@@ -1999,10 +1999,6 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
                                        nuke(&hw_ep->ep_out, -ESHUTDOWN);
                        }
                }
-
-               spin_unlock(&musb->lock);
-               driver->disconnect(&musb->g);
-               spin_lock(&musb->lock);
        }
 }
 
index d2e2efaba658c6c20c485e2de2d839b8a926d005..08c679c0dde5ae110a56ec70af33819fdd20cfeb 100644 (file)
@@ -405,7 +405,7 @@ int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
 /*
  *             platform functions
  */
-static int __devinit usbhs_probe(struct platform_device *pdev)
+static int usbhs_probe(struct platform_device *pdev)
 {
        struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
        struct renesas_usbhs_driver_callback *dfunc;
index 8da685e796d1484cadbb3bcda67a5ee26ac64c44..ffdf5d15085ebbe845dbd54474c8a0e5b9464061 100644 (file)
@@ -820,7 +820,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
        if (len % 4) /* 32bit alignment */
                goto usbhsf_pio_prepare_push;
 
-       if ((*(u32 *) pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
+       if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_push;
 
        /* get enable DMA fifo */
@@ -897,7 +897,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
        if (!fifo)
                goto usbhsf_pio_prepare_pop;
 
-       if ((*(u32 *) pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
+       if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_pop;
 
        ret = usbhsf_fifo_select(pipe, fifo, 0);
index 8ae3733031cdb8fa17ec146d31e5d42e9eea120a..6c6875533f019096af0518e6c92d9f430c4edc49 100644 (file)
@@ -143,8 +143,8 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod);
  */
 #if    defined(CONFIG_USB_RENESAS_USBHS_HCD) || \
        defined(CONFIG_USB_RENESAS_USBHS_HCD_MODULE)
-extern int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv);
-extern int __devexit usbhs_mod_host_remove(struct usbhs_priv *priv);
+extern int usbhs_mod_host_probe(struct usbhs_priv *priv);
+extern int usbhs_mod_host_remove(struct usbhs_priv *priv);
 #else
 static inline int usbhs_mod_host_probe(struct usbhs_priv *priv)
 {
@@ -157,8 +157,8 @@ static inline void usbhs_mod_host_remove(struct usbhs_priv *priv)
 
 #if    defined(CONFIG_USB_RENESAS_USBHS_UDC) || \
        defined(CONFIG_USB_RENESAS_USBHS_UDC_MODULE)
-extern int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv);
-extern void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv);
+extern int usbhs_mod_gadget_probe(struct usbhs_priv *priv);
+extern void usbhs_mod_gadget_remove(struct usbhs_priv *priv);
 #else
 static inline int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
index 4cc7ee0babc60441914ac69ca20a2fe1d857c5e6..d9717e0bc1ff65c6d23cae4bf0693c434d8873fe 100644 (file)
@@ -830,7 +830,7 @@ static int usbhsg_stop(struct usbhs_priv *priv)
        return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
 }
 
-int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
+int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
        struct usbhsg_gpriv *gpriv;
        struct usbhsg_uep *uep;
@@ -927,7 +927,7 @@ usbhs_mod_gadget_probe_err_gpriv:
        return ret;
 }
 
-void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv)
+void usbhs_mod_gadget_remove(struct usbhs_priv *priv)
 {
        struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
 
index 1a7208a50afc15dc42de21b7bcbf6184ac204ff3..bade761a1e52b783a63dfb462f8b11ef4c111999 100644 (file)
@@ -103,7 +103,7 @@ struct usbhsh_hpriv {
 
        u32     port_stat;      /* USB_PORT_STAT_xxx */
 
-       struct completion       *done;
+       struct completion       setup_ack_done;
 
        /* see usbhsh_req_alloc/free */
        struct list_head        ureq_link_active;
@@ -355,6 +355,7 @@ static void usbhsh_device_free(struct usbhsh_hpriv *hpriv,
 struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
                                        struct usbhsh_device *udev,
                                        struct usb_host_endpoint *ep,
+                                       int dir_in_req,
                                        gfp_t mem_flags)
 {
        struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
@@ -364,27 +365,38 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
        struct usbhs_pipe *pipe, *best_pipe;
        struct device *dev = usbhsh_hcd_to_dev(hcd);
        struct usb_endpoint_descriptor *desc = &ep->desc;
-       int type, i;
+       int type, i, dir_in;
        unsigned int min_usr;
 
+       dir_in_req = !!dir_in_req;
+
        uep = kzalloc(sizeof(struct usbhsh_ep), mem_flags);
        if (!uep) {
                dev_err(dev, "usbhsh_ep alloc fail\n");
                return NULL;
        }
-       type = usb_endpoint_type(desc);
+
+       if (usb_endpoint_xfer_control(desc)) {
+               best_pipe = usbhsh_hpriv_to_dcp(hpriv);
+               goto usbhsh_endpoint_alloc_find_pipe;
+       }
 
        /*
         * find best pipe for endpoint
         * see
         *      HARDWARE LIMITATION
         */
+       type = usb_endpoint_type(desc);
        min_usr = ~0;
        best_pipe = NULL;
-       usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
+       usbhs_for_each_pipe(pipe, priv, i) {
                if (!usbhs_pipe_type_is(pipe, type))
                        continue;
 
+               dir_in = !!usbhs_pipe_is_dir_in(pipe);
+               if (0 != (dir_in - dir_in_req))
+                       continue;
+
                info = usbhsh_pipe_info(pipe);
 
                if (min_usr > info->usr_cnt) {
@@ -398,7 +410,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
                kfree(uep);
                return NULL;
        }
-
+usbhsh_endpoint_alloc_find_pipe:
        /*
         * init uep
         */
@@ -423,6 +435,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
         * see
         *  DCPMAXP/PIPEMAXP
         */
+       usbhs_pipe_sequence_data0(uep->pipe);
        usbhs_pipe_config_update(uep->pipe,
                                 usbhsh_device_number(hpriv, udev),
                                 usb_endpoint_num(desc),
@@ -430,7 +443,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
 
        dev_dbg(dev, "%s [%d-%s](%p)\n", __func__,
                usbhsh_device_number(hpriv, udev),
-               usbhs_pipe_name(pipe), uep);
+               usbhs_pipe_name(uep->pipe), uep);
 
        return uep;
 }
@@ -549,8 +562,7 @@ static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv,
         *      usbhsh_irq_setup_ack()
         *      usbhsh_irq_setup_err()
         */
-       DECLARE_COMPLETION(done);
-       hpriv->done = &done;
+       init_completion(&hpriv->setup_ack_done);
 
        /* copy original request */
        memcpy(&req, urb->setup_packet, sizeof(struct usb_ctrlrequest));
@@ -572,8 +584,7 @@ static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv,
        /*
         * wait setup packet ACK
         */
-       wait_for_completion(&done);
-       hpriv->done = NULL;
+       wait_for_completion(&hpriv->setup_ack_done);
 
        dev_dbg(dev, "%s done\n", __func__);
 }
@@ -724,11 +735,11 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
        struct usbhsh_device *udev, *new_udev = NULL;
        struct usbhs_pipe *pipe;
        struct usbhsh_ep *uep;
+       int is_dir_in = usb_pipein(urb->pipe);
 
        int ret;
 
-       dev_dbg(dev, "%s (%s)\n",
-               __func__, usb_pipein(urb->pipe) ? "in" : "out");
+       dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out");
 
        ret = usb_hcd_link_urb_to_ep(hcd, urb);
        if (ret)
@@ -751,7 +762,8 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
         */
        uep = usbhsh_ep_to_uep(ep);
        if (!uep) {
-               uep = usbhsh_endpoint_alloc(hpriv, udev, ep, mem_flags);
+               uep = usbhsh_endpoint_alloc(hpriv, udev, ep,
+                                           is_dir_in, mem_flags);
                if (!uep)
                        goto usbhsh_urb_enqueue_error_free_device;
        }
@@ -1095,10 +1107,7 @@ static int usbhsh_irq_setup_ack(struct usbhs_priv *priv,
 
        dev_dbg(dev, "setup packet OK\n");
 
-       if (unlikely(!hpriv->done))
-               dev_err(dev, "setup ack happen without necessary data\n");
-       else
-               complete(hpriv->done); /* see usbhsh_urb_enqueue() */
+       complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */
 
        return 0;
 }
@@ -1111,10 +1120,7 @@ static int usbhsh_irq_setup_err(struct usbhs_priv *priv,
 
        dev_dbg(dev, "setup packet Err\n");
 
-       if (unlikely(!hpriv->done))
-               dev_err(dev, "setup err happen without necessary data\n");
-       else
-               complete(hpriv->done); /* see usbhsh_urb_enqueue() */
+       complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */
 
        return 0;
 }
@@ -1221,8 +1227,18 @@ static int usbhsh_stop(struct usbhs_priv *priv)
 {
        struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv);
        struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv);
+       struct usbhs_mod *mod = usbhs_mod_get_current(priv);
        struct device *dev = usbhs_priv_to_dev(priv);
 
+       /*
+        * disable irq callback
+        */
+       mod->irq_attch  = NULL;
+       mod->irq_dtch   = NULL;
+       mod->irq_sack   = NULL;
+       mod->irq_sign   = NULL;
+       usbhs_irq_callback_update(priv, mod);
+
        usb_remove_hcd(hcd);
 
        /* disable sys */
@@ -1235,7 +1251,7 @@ static int usbhsh_stop(struct usbhs_priv *priv)
        return 0;
 }
 
-int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv)
+int usbhs_mod_host_probe(struct usbhs_priv *priv)
 {
        struct usbhsh_hpriv *hpriv;
        struct usb_hcd *hcd;
@@ -1279,7 +1295,6 @@ int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv)
        hpriv->mod.stop         = usbhsh_stop;
        hpriv->pipe_info        = pipe_info;
        hpriv->pipe_size        = pipe_size;
-       hpriv->done             = NULL;
        usbhsh_req_list_init(hpriv);
        usbhsh_port_stat_init(hpriv);
 
@@ -1299,7 +1314,7 @@ usbhs_mod_host_probe_err:
        return -ENOMEM;
 }
 
-int __devexit usbhs_mod_host_remove(struct usbhs_priv *priv)
+int usbhs_mod_host_remove(struct usbhs_priv *priv)
 {
        struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv);
        struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv);
index 5cdb9d912275193bd7f5a8929742c4199a45c5c4..18e875b92e001d1c290f2b95e498eea77c6b72cb 100644 (file)
@@ -42,7 +42,7 @@ static int debug;
  * Version information
  */
 
-#define DRIVER_VERSION "v0.6"
+#define DRIVER_VERSION "v0.7"
 #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"
 #define DRIVER_DESC "USB ARK3116 serial/IrDA driver"
 #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA"
@@ -380,10 +380,6 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
                goto err_out;
        }
 
-       /* setup termios */
-       if (tty)
-               ark3116_set_termios(tty, port, NULL);
-
        /* remove any data still left: also clears error state */
        ark3116_read_reg(serial, UART_RX, buf);
 
@@ -406,6 +402,10 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
        /* enable DMA */
        ark3116_write_reg(port->serial, UART_FCR, UART_FCR_DMA_SELECT);
 
+       /* setup termios */
+       if (tty)
+               ark3116_set_termios(tty, port, NULL);
+
 err_out:
        kfree(buf);
        return result;
index 8fe034d2d3e7b1bf1c4b0471a1bfaff96ab218a7..bd4298bb6750d347f825c47026b8de0acb7096a1 100644 (file)
@@ -2104,13 +2104,19 @@ static void ftdi_set_termios(struct tty_struct *tty,
 
        cflag = termios->c_cflag;
 
-       /* FIXME -For this cut I don't care if the line is really changing or
-          not  - so just do the change regardless  - should be able to
-          compare old_termios and tty->termios */
+       if (old_termios->c_cflag == termios->c_cflag
+           && old_termios->c_ispeed == termios->c_ispeed
+           && old_termios->c_ospeed == termios->c_ospeed)
+               goto no_c_cflag_changes;
+
        /* NOTE These routines can get interrupted by
           ftdi_sio_read_bulk_callback  - need to examine what this means -
           don't see any problems yet */
 
+       if ((old_termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)) ==
+           (termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)))
+               goto no_data_parity_stop_changes;
+
        /* Set number of data bits, parity, stop bits */
 
        urb_value = 0;
@@ -2151,6 +2157,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
        }
 
        /* Now do the baudrate */
+no_data_parity_stop_changes:
        if ((cflag & CBAUD) == B0) {
                /* Disable flow control */
                if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -2178,6 +2185,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
 
        /* Set flow control */
        /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
+no_c_cflag_changes:
        if (cflag & CRTSCTS) {
                dbg("%s Setting to CRTSCTS flow control", __func__);
                if (usb_control_msg(dev,
index 89ae1f65e1b18bc46d8b8ccc0004cd94edb4ee40..d865878c9f97449a6168fd69198af63f647ac497 100644 (file)
@@ -156,6 +156,7 @@ static void option_instat_callback(struct urb *urb);
 #define HUAWEI_PRODUCT_K4511                   0x14CC
 #define HUAWEI_PRODUCT_ETS1220                 0x1803
 #define HUAWEI_PRODUCT_E353                    0x1506
+#define HUAWEI_PRODUCT_E173S                   0x1C05
 
 #define QUANTA_VENDOR_ID                       0x0408
 #define QUANTA_PRODUCT_Q101                    0xEA02
@@ -316,6 +317,9 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_AC8710                     0xfff1
 #define ZTE_PRODUCT_AC2726                     0xfff5
 #define ZTE_PRODUCT_AC8710T                    0xffff
+#define ZTE_PRODUCT_MC2718                     0xffe8
+#define ZTE_PRODUCT_AD3812                     0xffeb
+#define ZTE_PRODUCT_MC2716                     0xffed
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -468,6 +472,10 @@ static void option_instat_callback(struct urb *urb);
 #define YUGA_PRODUCT_CLU528                    0x260D
 #define YUGA_PRODUCT_CLU526                    0x260F
 
+/* Viettel products */
+#define VIETTEL_VENDOR_ID                      0x2262
+#define VIETTEL_PRODUCT_VT1000                 0x0002
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -500,6 +508,18 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = {
        .reserved = BIT(4),
 };
 
+static const struct option_blacklist_info zte_ad3812_z_blacklist = {
+       .sendsetup = BIT(0) | BIT(1) | BIT(2),
+};
+
+static const struct option_blacklist_info zte_mc2718_z_blacklist = {
+       .sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4),
+};
+
+static const struct option_blacklist_info zte_mc2716_z_blacklist = {
+       .sendsetup = BIT(1) | BIT(2) | BIT(3),
+};
+
 static const struct option_blacklist_info huawei_cdc12_blacklist = {
        .reserved = BIT(1) | BIT(2),
 };
@@ -622,6 +642,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
@@ -1043,6 +1064,12 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff),
+        .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff),
+        .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
+        .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
        { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
@@ -1141,6 +1168,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
+       { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 9083d1e616b4b48c30661ecd4261dfff3c127c14..fc2d66f7f4eb0ce3410a066e3877155651398eff 100644 (file)
@@ -91,7 +91,6 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
        { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
        { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
-       { USB_DEVICE(WINCHIPHEAD_VENDOR_ID, WINCHIPHEAD_USBSER_PRODUCT_ID) },
        { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
index 3d10d7f02072d10250f80802b7130fb941fb6793..c38b8c00c06fddd4c71f3508df13f592d2b4480b 100644 (file)
 #define ADLINK_VENDOR_ID               0x0b63
 #define ADLINK_ND6530_PRODUCT_ID       0x6530
 
-/* WinChipHead USB->RS 232 adapter */
-#define WINCHIPHEAD_VENDOR_ID          0x4348
-#define WINCHIPHEAD_USBSER_PRODUCT_ID  0x5523
-
 /* SMART USB Serial Adapter */
 #define SMART_VENDOR_ID        0x0b8c
 #define SMART_PRODUCT_ID       0x2303
index 4dca3ef0668c9963448289c3ab1160633865a6b9..9fbe742343c6cb6d023706bd7d5bd8170191d49e 100644 (file)
@@ -1762,10 +1762,9 @@ static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
                result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
        } else {
                void *buf;
-               int offset;
+               int offset = 0;
                u16 PhyBlockAddr;
                u8 PageNum;
-               u32 result;
                u16 len, oldphy, newphy;
 
                buf = kmalloc(blenByte, GFP_KERNEL);
index 93c1a4d86f51785983c5bac899d272808d390aff..82dd834709c78f7627b82a53d5e268fb006744a2 100644 (file)
@@ -59,7 +59,9 @@
 
 void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
 {
-       /* Pad the SCSI command with zeros out to 12 bytes
+       /*
+        * Pad the SCSI command with zeros out to 12 bytes.  If the
+        * command already is 12 bytes or longer, leave it alone.
         *
         * NOTE: This only works because a scsi_cmnd struct field contains
         * a unsigned char cmnd[16], so we know we have storage available
@@ -67,9 +69,6 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
        for (; srb->cmd_len<12; srb->cmd_len++)
                srb->cmnd[srb->cmd_len] = 0;
 
-       /* set command length to 12 bytes */
-       srb->cmd_len = 12;
-
        /* send the command to the transport layer */
        usb_stor_invoke_transport(srb, us);
 }
index 55f91d9ab00bd18bd01df877eab846a310595956..29577bf1f559070044ee2c9f50d300d86745f78e 100644 (file)
 /* Clock registers available only on Version 2 */
 #define  LCD_CLK_ENABLE_REG                    0x6c
 #define  LCD_CLK_RESET_REG                     0x70
+#define  LCD_CLK_MAIN_RESET                    BIT(3)
 
 #define LCD_NUM_BUFFERS        2
 
@@ -244,6 +245,10 @@ static inline void lcd_enable_raster(void)
 {
        u32 reg;
 
+       /* Bring LCDC out of reset */
+       if (lcd_revision == LCD_VERSION_2)
+               lcdc_write(0, LCD_CLK_RESET_REG);
+
        reg = lcdc_read(LCD_RASTER_CTRL_REG);
        if (!(reg & LCD_RASTER_ENABLE))
                lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
@@ -257,6 +262,10 @@ static inline void lcd_disable_raster(void)
        reg = lcdc_read(LCD_RASTER_CTRL_REG);
        if (reg & LCD_RASTER_ENABLE)
                lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+
+       if (lcd_revision == LCD_VERSION_2)
+               /* Write 1 to reset LCDC */
+               lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
 }
 
 static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
@@ -584,8 +593,12 @@ static void lcd_reset(struct da8xx_fb_par *par)
        lcdc_write(0, LCD_DMA_CTRL_REG);
        lcdc_write(0, LCD_RASTER_CTRL_REG);
 
-       if (lcd_revision == LCD_VERSION_2)
+       if (lcd_revision == LCD_VERSION_2) {
                lcdc_write(0, LCD_INT_ENABLE_SET_REG);
+               /* Write 1 to reset */
+               lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
+               lcdc_write(0, LCD_CLK_RESET_REG);
+       }
 }
 
 static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
index 0ccd7adf47bb2db54312287fb5191ac8ed4b2b94..6f61e781f15afa94ae4ebbca32b57407b648a47a 100644 (file)
@@ -19,6 +19,7 @@
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
index 3532782551cb80dfa6ee1254be24d669c2fb28ef..5c81533eacaa6224c3aed27d0c1e72a60616c3d7 100644 (file)
@@ -1720,12 +1720,11 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
        const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
        unsigned long fclk = 0;
 
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
-               if (width != out_width || height != out_height)
-                       return -EINVAL;
-               else
-                       return 0;
-       }
+       if (width == out_width && height == out_height)
+               return 0;
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
+               return -EINVAL;
 
        if (out_width < width / maxdownscale ||
                        out_width > width * 8)
index 3262f0f1fa35f395aec7637dc4e61f4fdf5766b1..c56378c555b0907255048e32384c1b5b191bc14f 100644 (file)
@@ -269,7 +269,7 @@ static void update_hdmi_timings(struct hdmi_config *cfg,
 unsigned long hdmi_get_pixel_clock(void)
 {
        /* HDMI Pixel Clock in Mhz */
-       return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000;
+       return hdmi.ip_data.cfg.timings.timings.pixel_clock * 1000;
 }
 
 static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
index 69d882cbe7095f0acde27c9e61e12ea3236948d8..c01c1c162726137e19197c112313aa7458a91e0b 100644 (file)
 #define M1200X720_R60_VSP       POSITIVE
 
 /* 1200x900@60 Sync Polarity (DCON) */
-#define M1200X900_R60_HSP       NEGATIVE
-#define M1200X900_R60_VSP       NEGATIVE
+#define M1200X900_R60_HSP       POSITIVE
+#define M1200X900_R60_VSP       POSITIVE
 
 /* 1280x600@60 Sync Polarity (GTF Mode) */
 #define M1280x600_R60_HSP       NEGATIVE
index 816ed08e7cf3c504f4ce5377b327964a30daa8e9..1a61939b85fce4f3a1269b7915b1e9c3760efe26 100644 (file)
@@ -37,7 +37,7 @@ config VIRTIO_BALLOON
 
  config VIRTIO_MMIO
        tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on HAS_IOMEM && EXPERIMENTAL
        select VIRTIO
        select VIRTIO_RING
        ---help---
index acc5e43c373eb25c3d24410a70a39392caf551f4..7317dc2ec426e495d54b27a46839e15b429400f2 100644 (file)
@@ -118,7 +118,7 @@ static void vm_finalize_features(struct virtio_device *vdev)
        vring_transport_features(vdev);
 
        for (i = 0; i < ARRAY_SIZE(vdev->features); i++) {
-               writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SET);
+               writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SEL);
                writel(vdev->features[i],
                                vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES);
        }
index 79a31e5b4b68143a43a370ee422453ac723b2af6..03d1984bd3635042b6bbe19f9966dfe89068e1ff 100644 (file)
@@ -169,11 +169,29 @@ static void vp_set_status(struct virtio_device *vdev, u8 status)
        iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
 }
 
+/* wait for pending irq handlers */
+static void vp_synchronize_vectors(struct virtio_device *vdev)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+       int i;
+
+       if (vp_dev->intx_enabled)
+               synchronize_irq(vp_dev->pci_dev->irq);
+
+       for (i = 0; i < vp_dev->msix_vectors; ++i)
+               synchronize_irq(vp_dev->msix_entries[i].vector);
+}
+
 static void vp_reset(struct virtio_device *vdev)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        /* 0 status means a reset. */
        iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+       /* Flush out the status write, and flush in device writes,
+        * including MSi-X interrupts, if any. */
+       ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+       /* Flush pending VQ/configuration callbacks. */
+       vp_synchronize_vectors(vdev);
 }
 
 /* the notify function used when creating a virt queue */
@@ -594,11 +612,11 @@ static struct virtio_config_ops virtio_pci_config_ops = {
 
 static void virtio_pci_release_dev(struct device *_d)
 {
-       struct virtio_device *dev = container_of(_d, struct virtio_device,
-                                                dev);
-       struct virtio_pci_device *vp_dev = to_vp_device(dev);
-
-       kfree(vp_dev);
+       /*
+        * No need for a release method as we allocate/free
+        * all devices together with the pci devices.
+        * Provide an empty one to avoid getting a warning from core.
+        */
 }
 
 /* the PCI probing function */
@@ -686,6 +704,7 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
        pci_iounmap(pci_dev, vp_dev->ioaddr);
        pci_release_regions(pci_dev);
        pci_disable_device(pci_dev);
+       kfree(vp_dev);
 }
 
 #ifdef CONFIG_PM
index 6285867a93568c5dd03576d5e5adf1779d7c21d1..79fd606b7cd5cad60f487120db2e3ebf408ddedb 100644 (file)
@@ -314,13 +314,6 @@ config NUC900_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called nuc900_wdt.
 
-config ADX_WATCHDOG
-       tristate "Avionic Design Xanthos watchdog"
-       depends on ARCH_PXA_ADX
-       help
-         Say Y here if you want support for the watchdog timer on Avionic
-         Design Xanthos boards.
-
 config TS72XX_WATCHDOG
        tristate "TS-72XX SBC Watchdog"
        depends on MACH_TS72XX
index 55bd5740e91000f1616da7ad0a4adf5eb4c33ac7..fe893e91935b6652e680b3b722ab3bb7b71bf3b3 100644 (file)
@@ -51,7 +51,6 @@ obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o
 obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
 obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
-obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
 
diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c
deleted file mode 100644 (file)
index af6e6b1..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Avionic Design GmbH
- *
- * 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/fs.h>
-#include <linux/gfp.h>
-#include <linux/io.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/uaccess.h>
-#include <linux/watchdog.h>
-
-#define WATCHDOG_NAME "adx-wdt"
-
-/* register offsets */
-#define        ADX_WDT_CONTROL         0x00
-#define        ADX_WDT_CONTROL_ENABLE  (1 << 0)
-#define        ADX_WDT_CONTROL_nRESET  (1 << 1)
-#define        ADX_WDT_TIMEOUT         0x08
-
-static struct platform_device *adx_wdt_dev;
-static unsigned long driver_open;
-
-#define        WDT_STATE_STOP  0
-#define        WDT_STATE_START 1
-
-struct adx_wdt {
-       void __iomem *base;
-       unsigned long timeout;
-       unsigned int state;
-       unsigned int wake;
-       spinlock_t lock;
-};
-
-static const struct watchdog_info adx_wdt_info = {
-       .identity = "Avionic Design Xanthos Watchdog",
-       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-};
-
-static void adx_wdt_start_locked(struct adx_wdt *wdt)
-{
-       u32 ctrl;
-
-       ctrl = readl(wdt->base + ADX_WDT_CONTROL);
-       ctrl |= ADX_WDT_CONTROL_ENABLE;
-       writel(ctrl, wdt->base + ADX_WDT_CONTROL);
-       wdt->state = WDT_STATE_START;
-}
-
-static void adx_wdt_start(struct adx_wdt *wdt)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&wdt->lock, flags);
-       adx_wdt_start_locked(wdt);
-       spin_unlock_irqrestore(&wdt->lock, flags);
-}
-
-static void adx_wdt_stop_locked(struct adx_wdt *wdt)
-{
-       u32 ctrl;
-
-       ctrl = readl(wdt->base + ADX_WDT_CONTROL);
-       ctrl &= ~ADX_WDT_CONTROL_ENABLE;
-       writel(ctrl, wdt->base + ADX_WDT_CONTROL);
-       wdt->state = WDT_STATE_STOP;
-}
-
-static void adx_wdt_stop(struct adx_wdt *wdt)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&wdt->lock, flags);
-       adx_wdt_stop_locked(wdt);
-       spin_unlock_irqrestore(&wdt->lock, flags);
-}
-
-static void adx_wdt_set_timeout(struct adx_wdt *wdt, unsigned long seconds)
-{
-       unsigned long timeout = seconds * 1000;
-       unsigned long flags;
-       unsigned int state;
-
-       spin_lock_irqsave(&wdt->lock, flags);
-       state = wdt->state;
-       adx_wdt_stop_locked(wdt);
-       writel(timeout, wdt->base + ADX_WDT_TIMEOUT);
-
-       if (state == WDT_STATE_START)
-               adx_wdt_start_locked(wdt);
-
-       wdt->timeout = timeout;
-       spin_unlock_irqrestore(&wdt->lock, flags);
-}
-
-static void adx_wdt_get_timeout(struct adx_wdt *wdt, unsigned long *seconds)
-{
-       *seconds = wdt->timeout / 1000;
-}
-
-static void adx_wdt_keepalive(struct adx_wdt *wdt)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&wdt->lock, flags);
-       writel(wdt->timeout, wdt->base + ADX_WDT_TIMEOUT);
-       spin_unlock_irqrestore(&wdt->lock, flags);
-}
-
-static int adx_wdt_open(struct inode *inode, struct file *file)
-{
-       struct adx_wdt *wdt = platform_get_drvdata(adx_wdt_dev);
-
-       if (test_and_set_bit(0, &driver_open))
-               return -EBUSY;
-
-       file->private_data = wdt;
-       adx_wdt_set_timeout(wdt, 30);
-       adx_wdt_start(wdt);
-
-       return nonseekable_open(inode, file);
-}
-
-static int adx_wdt_release(struct inode *inode, struct file *file)
-{
-       struct adx_wdt *wdt = file->private_data;
-
-       adx_wdt_stop(wdt);
-       clear_bit(0, &driver_open);
-
-       return 0;
-}
-
-static long adx_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct adx_wdt *wdt = file->private_data;
-       void __user *argp = (void __user *)arg;
-       unsigned long __user *p = argp;
-       unsigned long seconds = 0;
-       unsigned int options;
-       long ret = -EINVAL;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user(argp, &adx_wdt_info, sizeof(adx_wdt_info)))
-                       return -EFAULT;
-               else
-                       return 0;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-               adx_wdt_keepalive(wdt);
-               return 0;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(seconds, p))
-                       return -EFAULT;
-
-               adx_wdt_set_timeout(wdt, seconds);
-
-               /* fallthrough */
-       case WDIOC_GETTIMEOUT:
-               adx_wdt_get_timeout(wdt, &seconds);
-               return put_user(seconds, p);
-
-       case WDIOC_SETOPTIONS:
-               if (copy_from_user(&options, argp, sizeof(options)))
-                       return -EFAULT;
-
-               if (options & WDIOS_DISABLECARD) {
-                       adx_wdt_stop(wdt);
-                       ret = 0;
-               }
-
-               if (options & WDIOS_ENABLECARD) {
-                       adx_wdt_start(wdt);
-                       ret = 0;
-               }
-
-               return ret;
-
-       default:
-               break;
-       }
-
-       return -ENOTTY;
-}
-
-static ssize_t adx_wdt_write(struct file *file, const char __user *data,
-               size_t len, loff_t *ppos)
-{
-       struct adx_wdt *wdt = file->private_data;
-
-       if (len)
-               adx_wdt_keepalive(wdt);
-
-       return len;
-}
-
-static const struct file_operations adx_wdt_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .open = adx_wdt_open,
-       .release = adx_wdt_release,
-       .unlocked_ioctl = adx_wdt_ioctl,
-       .write = adx_wdt_write,
-};
-
-static struct miscdevice adx_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &adx_wdt_fops,
-};
-
-static int __devinit adx_wdt_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       struct adx_wdt *wdt;
-       int ret = 0;
-       u32 ctrl;
-
-       wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
-       if (!wdt) {
-               dev_err(&pdev->dev, "cannot allocate WDT structure\n");
-               return -ENOMEM;
-       }
-
-       spin_lock_init(&wdt->lock);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "cannot obtain I/O memory region\n");
-               return -ENXIO;
-       }
-
-       res = devm_request_mem_region(&pdev->dev, res->start,
-                       resource_size(res), res->name);
-       if (!res) {
-               dev_err(&pdev->dev, "cannot request I/O memory region\n");
-               return -ENXIO;
-       }
-
-       wdt->base = devm_ioremap_nocache(&pdev->dev, res->start,
-                       resource_size(res));
-       if (!wdt->base) {
-               dev_err(&pdev->dev, "cannot remap I/O memory region\n");
-               return -ENXIO;
-       }
-
-       /* disable watchdog and reboot on timeout */
-       ctrl = readl(wdt->base + ADX_WDT_CONTROL);
-       ctrl &= ~ADX_WDT_CONTROL_ENABLE;
-       ctrl &= ~ADX_WDT_CONTROL_nRESET;
-       writel(ctrl, wdt->base + ADX_WDT_CONTROL);
-
-       platform_set_drvdata(pdev, wdt);
-       adx_wdt_dev = pdev;
-
-       ret = misc_register(&adx_wdt_miscdev);
-       if (ret) {
-               dev_err(&pdev->dev, "cannot register miscdev on minor %d "
-                               "(err=%d)\n", WATCHDOG_MINOR, ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int __devexit adx_wdt_remove(struct platform_device *pdev)
-{
-       struct adx_wdt *wdt = platform_get_drvdata(pdev);
-
-       misc_deregister(&adx_wdt_miscdev);
-       adx_wdt_stop(wdt);
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-static void adx_wdt_shutdown(struct platform_device *pdev)
-{
-       struct adx_wdt *wdt = platform_get_drvdata(pdev);
-       adx_wdt_stop(wdt);
-}
-
-#ifdef CONFIG_PM
-static int adx_wdt_suspend(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct adx_wdt *wdt = platform_get_drvdata(pdev);
-
-       wdt->wake = (wdt->state == WDT_STATE_START) ? 1 : 0;
-       adx_wdt_stop(wdt);
-
-       return 0;
-}
-
-static int adx_wdt_resume(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct adx_wdt *wdt = platform_get_drvdata(pdev);
-
-       if (wdt->wake)
-               adx_wdt_start(wdt);
-
-       return 0;
-}
-
-static const struct dev_pm_ops adx_wdt_pm_ops = {
-       .suspend = adx_wdt_suspend,
-       .resume = adx_wdt_resume,
-};
-
-#  define ADX_WDT_PM_OPS       (&adx_wdt_pm_ops)
-#else
-#  define ADX_WDT_PM_OPS       NULL
-#endif
-
-static struct platform_driver adx_wdt_driver = {
-       .probe = adx_wdt_probe,
-       .remove = __devexit_p(adx_wdt_remove),
-       .shutdown = adx_wdt_shutdown,
-       .driver = {
-               .name = WATCHDOG_NAME,
-               .owner = THIS_MODULE,
-               .pm = ADX_WDT_PM_OPS,
-       },
-};
-
-static int __init adx_wdt_init(void)
-{
-       return platform_driver_register(&adx_wdt_driver);
-}
-
-static void __exit adx_wdt_exit(void)
-{
-       platform_driver_unregister(&adx_wdt_driver);
-}
-
-module_init(adx_wdt_init);
-module_exit(adx_wdt_exit);
-
-MODULE_DESCRIPTION("Avionic Design Xanthos Watchdog Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index 5de7e4fa5b8a62fcc3f366f760a4f2b7e985cfff..a79e3840782ad3f286f0971b4a3cd7f6d5a1ff0b 100644 (file)
@@ -401,8 +401,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 
        dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n",
                 (wtcon & S3C2410_WTCON_ENABLE) ?  "" : "in",
-                (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis",
-                (wtcon & S3C2410_WTCON_INTEN) ? "" : "en");
+                (wtcon & S3C2410_WTCON_RSTEN) ? "en" : "dis",
+                (wtcon & S3C2410_WTCON_INTEN) ? "en" : "dis");
 
        return 0;
 
index 7be38556aed0c5b0854a89704875218f15437b02..e789a47db41f4dc1c618efaba3c8e189851c42bb 100644 (file)
@@ -150,7 +150,7 @@ static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev,
                if (wm831x_wdt_cfgs[i].time == timeout)
                        break;
        if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
-               ret = -EINVAL;
+               return -EINVAL;
 
        ret = wm831x_reg_unlock(wm831x);
        if (ret == 0) {
index a767884a6c7a10cfb526aff86de7b0ca1848eb9f..31ab82fda38a264cd045c4b52c117eb375f8e80e 100644 (file)
@@ -501,7 +501,7 @@ EXPORT_SYMBOL_GPL(balloon_set_new_target);
  * alloc_xenballooned_pages - get pages that have been ballooned out
  * @nr_pages: Number of pages to get
  * @pages: pages returned
- * @highmem: highmem or lowmem pages
+ * @highmem: allow highmem pages
  * @return 0 on success, error otherwise
  */
 int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
@@ -511,7 +511,7 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
        mutex_lock(&balloon_mutex);
        while (pgno < nr_pages) {
                page = balloon_retrieve(highmem);
-               if (page && PageHighMem(page) == highmem) {
+               if (page && (highmem || !PageHighMem(page))) {
                        pages[pgno++] = page;
                } else {
                        enum bp_state st;
index f6832f46aea4a4861368465321cc8423f997cdfc..e1c4c6e5b469c44449f68e9e841d264eb08dbc48 100644 (file)
@@ -135,7 +135,7 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op,
                /* Grant foreign access to the page. */
                gref->gref_id = gnttab_grant_foreign_access(op->domid,
                        pfn_to_mfn(page_to_pfn(gref->page)), readonly);
-               if (gref->gref_id < 0) {
+               if ((int)gref->gref_id < 0) {
                        rc = gref->gref_id;
                        goto undo;
                }
@@ -280,7 +280,7 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv,
                goto out;
        }
 
-       gref_ids = kzalloc(sizeof(gref_ids[0]) * op.count, GFP_TEMPORARY);
+       gref_ids = kcalloc(op.count, sizeof(gref_ids[0]), GFP_TEMPORARY);
        if (!gref_ids) {
                rc = -ENOMEM;
                goto out;
index 39871326afa2ebb5905d2f6afbc922bb08826d0a..afca14d9042e6cd2ae03f238143ac8188aaf35fb 100644 (file)
@@ -114,11 +114,11 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
        if (NULL == add)
                return NULL;
 
-       add->grants    = kzalloc(sizeof(add->grants[0])    * count, GFP_KERNEL);
-       add->map_ops   = kzalloc(sizeof(add->map_ops[0])   * count, GFP_KERNEL);
-       add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL);
-       add->kmap_ops  = kzalloc(sizeof(add->kmap_ops[0])  * count, GFP_KERNEL);
-       add->pages     = kzalloc(sizeof(add->pages[0])     * count, GFP_KERNEL);
+       add->grants    = kcalloc(count, sizeof(add->grants[0]), GFP_KERNEL);
+       add->map_ops   = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL);
+       add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL);
+       add->kmap_ops  = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL);
+       add->pages     = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL);
        if (NULL == add->grants    ||
            NULL == add->map_ops   ||
            NULL == add->unmap_ops ||
index 81c3ce6b8bbeed198a77f22e21f2031131a82f42..1906125eab491bb384293c4424c27b8f0477e6f0 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/vmalloc.h>
 #include <linux/export.h>
 #include <asm/xen/hypervisor.h>
+#include <asm/xen/page.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/event_channel.h>
 #include <xen/events.h>
@@ -436,19 +437,20 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
 int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
 {
        struct gnttab_map_grant_ref op = {
-               .flags = GNTMAP_host_map,
+               .flags = GNTMAP_host_map | GNTMAP_contains_pte,
                .ref   = gnt_ref,
                .dom   = dev->otherend_id,
        };
        struct vm_struct *area;
+       pte_t *pte;
 
        *vaddr = NULL;
 
-       area = alloc_vm_area(PAGE_SIZE);
+       area = alloc_vm_area(PAGE_SIZE, &pte);
        if (!area)
                return -ENOMEM;
 
-       op.host_addr = (unsigned long)area->addr;
+       op.host_addr = arbitrary_virt_to_machine(pte).maddr;
 
        if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
                BUG();
@@ -527,6 +529,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
        struct gnttab_unmap_grant_ref op = {
                .host_addr = (unsigned long)vaddr,
        };
+       unsigned int level;
 
        /* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr)
         * method so that we don't have to muck with vmalloc internals here.
@@ -548,6 +551,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
        }
 
        op.handle = (grant_handle_t)area->phys_addr;
+       op.host_addr = arbitrary_virt_to_machine(
+               lookup_address((unsigned long)vaddr, &level)).maddr;
 
        if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
                BUG();
index 41c93c72224457179bda4ca18798b6f2add617c9..b1fe82cf88cfe0864a2d9603b713f8caacecde4e 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -337,7 +337,7 @@ static void bio_fs_destructor(struct bio *bio)
  *     RETURNS:
  *     Pointer to new bio on success, NULL on failure.
  */
-struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
+struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
        struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
 
@@ -365,7 +365,7 @@ static void bio_kmalloc_destructor(struct bio *bio)
  *   %__GFP_WAIT, the allocation is guaranteed to succeed.
  *
  **/
-struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs)
+struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
        struct bio *bio;
 
@@ -696,7 +696,8 @@ static void bio_free_map_data(struct bio_map_data *bmd)
        kfree(bmd);
 }
 
-static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count,
+static struct bio_map_data *bio_alloc_map_data(int nr_segs,
+                                              unsigned int iov_count,
                                               gfp_t gfp_mask)
 {
        struct bio_map_data *bmd;
index 8855aad3929c337cb1891cd63c702ff1b69e9322..22c64fff1bd524b213ce8b13a233f861680d8424 100644 (file)
@@ -683,7 +683,7 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,
                return PTR_ERR(fspath);
 
        if (fspath > fspath_min) {
-               ipath->fspath->val[i] = (u64)fspath;
+               ipath->fspath->val[i] = (u64)(unsigned long)fspath;
                ++ipath->fspath->elem_cnt;
                ipath->fspath->bytes_left = fspath - fspath_min;
        } else {
index 5a5d325a3935117a7c6002189b2d9206e9f60e68..634608d2a6d03b5d8741e573de0b142ff8cb6310 100644 (file)
@@ -147,14 +147,12 @@ struct btrfs_inode {
         * the btrfs file release call will add this inode to the
         * ordered operations list so that we make sure to flush out any
         * new data the application may have written before commit.
-        *
-        * yes, its silly to have a single bitflag, but we might grow more
-        * of these.
         */
        unsigned ordered_data_close:1;
        unsigned orphan_meta_reserved:1;
        unsigned dummy_inode:1;
        unsigned in_defrag:1;
+       unsigned delalloc_meta_reserved:1;
 
        /*
         * always compress this one file
index 0fe615e4ea387582acc06f60cac81366f23fe069..dede441bdeee2678225187bece170710abe1a9b4 100644 (file)
@@ -514,10 +514,25 @@ static inline int should_cow_block(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
                                   struct extent_buffer *buf)
 {
+       /* ensure we can see the force_cow */
+       smp_rmb();
+
+       /*
+        * We do not need to cow a block if
+        * 1) this block is not created or changed in this transaction;
+        * 2) this block does not belong to TREE_RELOC tree;
+        * 3) the root is not forced COW.
+        *
+        * What is forced COW:
+        *    when we create snapshot during commiting the transaction,
+        *    after we've finished coping src root, we must COW the shared
+        *    block to ensure the metadata consistency.
+        */
        if (btrfs_header_generation(buf) == trans->transid &&
            !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN) &&
            !(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID &&
-             btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)))
+             btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)) &&
+           !root->force_cow)
                return 0;
        return 1;
 }
index b9ba59ff9292559330745b8afb41eefacfbf1615..50634abef9b4a51336e95b8bc2aafb4edb7844a0 100644 (file)
@@ -848,7 +848,8 @@ struct btrfs_free_cluster {
 enum btrfs_caching_type {
        BTRFS_CACHE_NO          = 0,
        BTRFS_CACHE_STARTED     = 1,
-       BTRFS_CACHE_FINISHED    = 2,
+       BTRFS_CACHE_FAST        = 2,
+       BTRFS_CACHE_FINISHED    = 3,
 };
 
 enum btrfs_disk_cache_state {
@@ -1271,6 +1272,8 @@ struct btrfs_root {
         * for stat.  It may be used for more later
         */
        dev_t anon_dev;
+
+       int force_cow;
 };
 
 struct btrfs_ioctl_defrag_range_args {
@@ -2366,6 +2369,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root,
 int btrfs_block_rsv_refill(struct btrfs_root *root,
                          struct btrfs_block_rsv *block_rsv,
                          u64 min_reserved);
+int btrfs_block_rsv_refill_noflush(struct btrfs_root *root,
+                                  struct btrfs_block_rsv *block_rsv,
+                                  u64 min_reserved);
 int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
                            struct btrfs_block_rsv *dst_rsv,
                            u64 num_bytes);
index 3a1b939c9ae2a7d0617946340dafa534baa402e6..5b163572e0ca7ddd6d5f8ef6ff6783dbd5871c4d 100644 (file)
@@ -617,12 +617,14 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root,
 static int btrfs_delayed_inode_reserve_metadata(
                                        struct btrfs_trans_handle *trans,
                                        struct btrfs_root *root,
+                                       struct inode *inode,
                                        struct btrfs_delayed_node *node)
 {
        struct btrfs_block_rsv *src_rsv;
        struct btrfs_block_rsv *dst_rsv;
        u64 num_bytes;
        int ret;
+       int release = false;
 
        src_rsv = trans->block_rsv;
        dst_rsv = &root->fs_info->delayed_block_rsv;
@@ -652,12 +654,65 @@ static int btrfs_delayed_inode_reserve_metadata(
                if (!ret)
                        node->bytes_reserved = num_bytes;
                return ret;
+       } else if (src_rsv == &root->fs_info->delalloc_block_rsv) {
+               spin_lock(&BTRFS_I(inode)->lock);
+               if (BTRFS_I(inode)->delalloc_meta_reserved) {
+                       BTRFS_I(inode)->delalloc_meta_reserved = 0;
+                       spin_unlock(&BTRFS_I(inode)->lock);
+                       release = true;
+                       goto migrate;
+               }
+               spin_unlock(&BTRFS_I(inode)->lock);
+
+               /* Ok we didn't have space pre-reserved.  This shouldn't happen
+                * too often but it can happen if we do delalloc to an existing
+                * inode which gets dirtied because of the time update, and then
+                * isn't touched again until after the transaction commits and
+                * then we try to write out the data.  First try to be nice and
+                * reserve something strictly for us.  If not be a pain and try
+                * to steal from the delalloc block rsv.
+                */
+               ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes);
+               if (!ret)
+                       goto out;
+
+               ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
+               if (!ret)
+                       goto out;
+
+               /*
+                * Ok this is a problem, let's just steal from the global rsv
+                * since this really shouldn't happen that often.
+                */
+               WARN_ON(1);
+               ret = btrfs_block_rsv_migrate(&root->fs_info->global_block_rsv,
+                                             dst_rsv, num_bytes);
+               goto out;
        }
 
+migrate:
        ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
+
+out:
+       /*
+        * Migrate only takes a reservation, it doesn't touch the size of the
+        * block_rsv.  This is to simplify people who don't normally have things
+        * migrated from their block rsv.  If they go to release their
+        * reservation, that will decrease the size as well, so if migrate
+        * reduced size we'd end up with a negative size.  But for the
+        * delalloc_meta_reserved stuff we will only know to drop 1 reservation,
+        * but we could in fact do this reserve/migrate dance several times
+        * between the time we did the original reservation and we'd clean it
+        * up.  So to take care of this, release the space for the meta
+        * reservation here.  I think it may be time for a documentation page on
+        * how block rsvs. work.
+        */
        if (!ret)
                node->bytes_reserved = num_bytes;
 
+       if (release)
+               btrfs_block_rsv_release(root, src_rsv, num_bytes);
+
        return ret;
 }
 
@@ -1708,7 +1763,8 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,
                goto release_node;
        }
 
-       ret = btrfs_delayed_inode_reserve_metadata(trans, root, delayed_node);
+       ret = btrfs_delayed_inode_reserve_metadata(trans, root, inode,
+                                                  delayed_node);
        if (ret)
                goto release_node;
 
index 102c176fc29c0b2bfed6259d259203347a9f6a07..632f8f3cc9db67f4173ca591b1b66d9ed898627f 100644 (file)
@@ -620,7 +620,7 @@ out:
 
 static int btree_io_failed_hook(struct bio *failed_bio,
                         struct page *page, u64 start, u64 end,
-                        u64 mirror_num, struct extent_state *state)
+                        int mirror_num, struct extent_state *state)
 {
        struct extent_io_tree *tree;
        unsigned long len;
@@ -1890,31 +1890,32 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        u64 features;
        struct btrfs_key location;
        struct buffer_head *bh;
-       struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root),
-                                                GFP_NOFS);
-       struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root),
-                                                GFP_NOFS);
+       struct btrfs_super_block *disk_super;
        struct btrfs_root *tree_root = btrfs_sb(sb);
-       struct btrfs_fs_info *fs_info = NULL;
-       struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root),
-                                               GFP_NOFS);
-       struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
-                                             GFP_NOFS);
+       struct btrfs_fs_info *fs_info = tree_root->fs_info;
+       struct btrfs_root *extent_root;
+       struct btrfs_root *csum_root;
+       struct btrfs_root *chunk_root;
+       struct btrfs_root *dev_root;
        struct btrfs_root *log_tree_root;
-
        int ret;
        int err = -EINVAL;
        int num_backups_tried = 0;
        int backup_index = 0;
 
-       struct btrfs_super_block *disk_super;
+       extent_root = fs_info->extent_root =
+               kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       csum_root = fs_info->csum_root =
+               kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       chunk_root = fs_info->chunk_root =
+               kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       dev_root = fs_info->dev_root =
+               kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
 
-       if (!extent_root || !tree_root || !tree_root->fs_info ||
-           !chunk_root || !dev_root || !csum_root) {
+       if (!extent_root || !csum_root || !chunk_root || !dev_root) {
                err = -ENOMEM;
                goto fail;
        }
-       fs_info = tree_root->fs_info;
 
        ret = init_srcu_struct(&fs_info->subvol_srcu);
        if (ret) {
@@ -1954,12 +1955,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        mutex_init(&fs_info->reloc_mutex);
 
        init_completion(&fs_info->kobj_unregister);
-       fs_info->tree_root = tree_root;
-       fs_info->extent_root = extent_root;
-       fs_info->csum_root = csum_root;
-       fs_info->chunk_root = chunk_root;
-       fs_info->dev_root = dev_root;
-       fs_info->fs_devices = fs_devices;
        INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
        INIT_LIST_HEAD(&fs_info->space_info);
        btrfs_mapping_init(&fs_info->mapping_tree);
@@ -2465,21 +2460,20 @@ fail_sb_buffer:
        btrfs_stop_workers(&fs_info->caching_workers);
 fail_alloc:
 fail_iput:
+       btrfs_mapping_tree_free(&fs_info->mapping_tree);
+
        invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
        iput(fs_info->btree_inode);
-
-       btrfs_close_devices(fs_info->fs_devices);
-       btrfs_mapping_tree_free(&fs_info->mapping_tree);
 fail_bdi:
        bdi_destroy(&fs_info->bdi);
 fail_srcu:
        cleanup_srcu_struct(&fs_info->subvol_srcu);
 fail:
+       btrfs_close_devices(fs_info->fs_devices);
        free_fs_info(fs_info);
        return ERR_PTR(err);
 
 recovery_tree_root:
-
        if (!btrfs_test_opt(tree_root, RECOVERY))
                goto fail_tree_roots;
 
@@ -2579,22 +2573,10 @@ static int write_dev_supers(struct btrfs_device *device,
        int errors = 0;
        u32 crc;
        u64 bytenr;
-       int last_barrier = 0;
 
        if (max_mirrors == 0)
                max_mirrors = BTRFS_SUPER_MIRROR_MAX;
 
-       /* make sure only the last submit_bh does a barrier */
-       if (do_barriers) {
-               for (i = 0; i < max_mirrors; i++) {
-                       bytenr = btrfs_sb_offset(i);
-                       if (bytenr + BTRFS_SUPER_INFO_SIZE >=
-                           device->total_bytes)
-                               break;
-                       last_barrier = i;
-               }
-       }
-
        for (i = 0; i < max_mirrors; i++) {
                bytenr = btrfs_sb_offset(i);
                if (bytenr + BTRFS_SUPER_INFO_SIZE >= device->total_bytes)
@@ -2640,17 +2622,136 @@ static int write_dev_supers(struct btrfs_device *device,
                        bh->b_end_io = btrfs_end_buffer_write_sync;
                }
 
-               if (i == last_barrier && do_barriers)
-                       ret = submit_bh(WRITE_FLUSH_FUA, bh);
-               else
-                       ret = submit_bh(WRITE_SYNC, bh);
-
+               /*
+                * we fua the first super.  The others we allow
+                * to go down lazy.
+                */
+               ret = submit_bh(WRITE_FUA, bh);
                if (ret)
                        errors++;
        }
        return errors < i ? 0 : -1;
 }
 
+/*
+ * endio for the write_dev_flush, this will wake anyone waiting
+ * for the barrier when it is done
+ */
+static void btrfs_end_empty_barrier(struct bio *bio, int err)
+{
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
+               clear_bit(BIO_UPTODATE, &bio->bi_flags);
+       }
+       if (bio->bi_private)
+               complete(bio->bi_private);
+       bio_put(bio);
+}
+
+/*
+ * trigger flushes for one the devices.  If you pass wait == 0, the flushes are
+ * sent down.  With wait == 1, it waits for the previous flush.
+ *
+ * any device where the flush fails with eopnotsupp are flagged as not-barrier
+ * capable
+ */
+static int write_dev_flush(struct btrfs_device *device, int wait)
+{
+       struct bio *bio;
+       int ret = 0;
+
+       if (device->nobarriers)
+               return 0;
+
+       if (wait) {
+               bio = device->flush_bio;
+               if (!bio)
+                       return 0;
+
+               wait_for_completion(&device->flush_wait);
+
+               if (bio_flagged(bio, BIO_EOPNOTSUPP)) {
+                       printk("btrfs: disabling barriers on dev %s\n",
+                              device->name);
+                       device->nobarriers = 1;
+               }
+               if (!bio_flagged(bio, BIO_UPTODATE)) {
+                       ret = -EIO;
+               }
+
+               /* drop the reference from the wait == 0 run */
+               bio_put(bio);
+               device->flush_bio = NULL;
+
+               return ret;
+       }
+
+       /*
+        * one reference for us, and we leave it for the
+        * caller
+        */
+       device->flush_bio = NULL;;
+       bio = bio_alloc(GFP_NOFS, 0);
+       if (!bio)
+               return -ENOMEM;
+
+       bio->bi_end_io = btrfs_end_empty_barrier;
+       bio->bi_bdev = device->bdev;
+       init_completion(&device->flush_wait);
+       bio->bi_private = &device->flush_wait;
+       device->flush_bio = bio;
+
+       bio_get(bio);
+       submit_bio(WRITE_FLUSH, bio);
+
+       return 0;
+}
+
+/*
+ * send an empty flush down to each device in parallel,
+ * then wait for them
+ */
+static int barrier_all_devices(struct btrfs_fs_info *info)
+{
+       struct list_head *head;
+       struct btrfs_device *dev;
+       int errors = 0;
+       int ret;
+
+       /* send down all the barriers */
+       head = &info->fs_devices->devices;
+       list_for_each_entry_rcu(dev, head, dev_list) {
+               if (!dev->bdev) {
+                       errors++;
+                       continue;
+               }
+               if (!dev->in_fs_metadata || !dev->writeable)
+                       continue;
+
+               ret = write_dev_flush(dev, 0);
+               if (ret)
+                       errors++;
+       }
+
+       /* wait for all the barriers */
+       list_for_each_entry_rcu(dev, head, dev_list) {
+               if (!dev->bdev) {
+                       errors++;
+                       continue;
+               }
+               if (!dev->in_fs_metadata || !dev->writeable)
+                       continue;
+
+               ret = write_dev_flush(dev, 1);
+               if (ret)
+                       errors++;
+       }
+       if (errors)
+               return -EIO;
+       return 0;
+}
+
 int write_all_supers(struct btrfs_root *root, int max_mirrors)
 {
        struct list_head *head;
@@ -2672,6 +2773,10 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
 
        mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
        head = &root->fs_info->fs_devices->devices;
+
+       if (do_barriers)
+               barrier_all_devices(root->fs_info);
+
        list_for_each_entry_rcu(dev, head, dev_list) {
                if (!dev->bdev) {
                        total_errors++;
index 9879bd474632eb59ab2cb73bdbc62dc8ce4db927..f0d5718d2587a43c96101c3408a0749fc4abefa0 100644 (file)
@@ -467,13 +467,59 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
                             struct btrfs_root *root,
                             int load_cache_only)
 {
+       DEFINE_WAIT(wait);
        struct btrfs_fs_info *fs_info = cache->fs_info;
        struct btrfs_caching_control *caching_ctl;
        int ret = 0;
 
-       smp_mb();
-       if (cache->cached != BTRFS_CACHE_NO)
+       caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS);
+       BUG_ON(!caching_ctl);
+
+       INIT_LIST_HEAD(&caching_ctl->list);
+       mutex_init(&caching_ctl->mutex);
+       init_waitqueue_head(&caching_ctl->wait);
+       caching_ctl->block_group = cache;
+       caching_ctl->progress = cache->key.objectid;
+       atomic_set(&caching_ctl->count, 1);
+       caching_ctl->work.func = caching_thread;
+
+       spin_lock(&cache->lock);
+       /*
+        * This should be a rare occasion, but this could happen I think in the
+        * case where one thread starts to load the space cache info, and then
+        * some other thread starts a transaction commit which tries to do an
+        * allocation while the other thread is still loading the space cache
+        * info.  The previous loop should have kept us from choosing this block
+        * group, but if we've moved to the state where we will wait on caching
+        * block groups we need to first check if we're doing a fast load here,
+        * so we can wait for it to finish, otherwise we could end up allocating
+        * from a block group who's cache gets evicted for one reason or
+        * another.
+        */
+       while (cache->cached == BTRFS_CACHE_FAST) {
+               struct btrfs_caching_control *ctl;
+
+               ctl = cache->caching_ctl;
+               atomic_inc(&ctl->count);
+               prepare_to_wait(&ctl->wait, &wait, TASK_UNINTERRUPTIBLE);
+               spin_unlock(&cache->lock);
+
+               schedule();
+
+               finish_wait(&ctl->wait, &wait);
+               put_caching_control(ctl);
+               spin_lock(&cache->lock);
+       }
+
+       if (cache->cached != BTRFS_CACHE_NO) {
+               spin_unlock(&cache->lock);
+               kfree(caching_ctl);
                return 0;
+       }
+       WARN_ON(cache->caching_ctl);
+       cache->caching_ctl = caching_ctl;
+       cache->cached = BTRFS_CACHE_FAST;
+       spin_unlock(&cache->lock);
 
        /*
         * We can't do the read from on-disk cache during a commit since we need
@@ -484,56 +530,51 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
        if (trans && (!trans->transaction->in_commit) &&
            (root && root != root->fs_info->tree_root) &&
            btrfs_test_opt(root, SPACE_CACHE)) {
-               spin_lock(&cache->lock);
-               if (cache->cached != BTRFS_CACHE_NO) {
-                       spin_unlock(&cache->lock);
-                       return 0;
-               }
-               cache->cached = BTRFS_CACHE_STARTED;
-               spin_unlock(&cache->lock);
-
                ret = load_free_space_cache(fs_info, cache);
 
                spin_lock(&cache->lock);
                if (ret == 1) {
+                       cache->caching_ctl = NULL;
                        cache->cached = BTRFS_CACHE_FINISHED;
                        cache->last_byte_to_unpin = (u64)-1;
                } else {
-                       cache->cached = BTRFS_CACHE_NO;
+                       if (load_cache_only) {
+                               cache->caching_ctl = NULL;
+                               cache->cached = BTRFS_CACHE_NO;
+                       } else {
+                               cache->cached = BTRFS_CACHE_STARTED;
+                       }
                }
                spin_unlock(&cache->lock);
+               wake_up(&caching_ctl->wait);
                if (ret == 1) {
+                       put_caching_control(caching_ctl);
                        free_excluded_extents(fs_info->extent_root, cache);
                        return 0;
                }
+       } else {
+               /*
+                * We are not going to do the fast caching, set cached to the
+                * appropriate value and wakeup any waiters.
+                */
+               spin_lock(&cache->lock);
+               if (load_cache_only) {
+                       cache->caching_ctl = NULL;
+                       cache->cached = BTRFS_CACHE_NO;
+               } else {
+                       cache->cached = BTRFS_CACHE_STARTED;
+               }
+               spin_unlock(&cache->lock);
+               wake_up(&caching_ctl->wait);
        }
 
-       if (load_cache_only)
-               return 0;
-
-       caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS);
-       BUG_ON(!caching_ctl);
-
-       INIT_LIST_HEAD(&caching_ctl->list);
-       mutex_init(&caching_ctl->mutex);
-       init_waitqueue_head(&caching_ctl->wait);
-       caching_ctl->block_group = cache;
-       caching_ctl->progress = cache->key.objectid;
-       /* one for caching kthread, one for caching block group list */
-       atomic_set(&caching_ctl->count, 2);
-       caching_ctl->work.func = caching_thread;
-
-       spin_lock(&cache->lock);
-       if (cache->cached != BTRFS_CACHE_NO) {
-               spin_unlock(&cache->lock);
-               kfree(caching_ctl);
+       if (load_cache_only) {
+               put_caching_control(caching_ctl);
                return 0;
        }
-       cache->caching_ctl = caching_ctl;
-       cache->cached = BTRFS_CACHE_STARTED;
-       spin_unlock(&cache->lock);
 
        down_write(&fs_info->extent_commit_sem);
+       atomic_inc(&caching_ctl->count);
        list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups);
        up_write(&fs_info->extent_commit_sem);
 
@@ -3797,16 +3838,16 @@ void btrfs_free_block_rsv(struct btrfs_root *root,
        kfree(rsv);
 }
 
-int btrfs_block_rsv_add(struct btrfs_root *root,
-                       struct btrfs_block_rsv *block_rsv,
-                       u64 num_bytes)
+static inline int __block_rsv_add(struct btrfs_root *root,
+                                 struct btrfs_block_rsv *block_rsv,
+                                 u64 num_bytes, int flush)
 {
        int ret;
 
        if (num_bytes == 0)
                return 0;
 
-       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 1);
+       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
        if (!ret) {
                block_rsv_add_bytes(block_rsv, num_bytes, 1);
                return 0;
@@ -3815,22 +3856,18 @@ int btrfs_block_rsv_add(struct btrfs_root *root,
        return ret;
 }
 
+int btrfs_block_rsv_add(struct btrfs_root *root,
+                       struct btrfs_block_rsv *block_rsv,
+                       u64 num_bytes)
+{
+       return __block_rsv_add(root, block_rsv, num_bytes, 1);
+}
+
 int btrfs_block_rsv_add_noflush(struct btrfs_root *root,
                                struct btrfs_block_rsv *block_rsv,
                                u64 num_bytes)
 {
-       int ret;
-
-       if (num_bytes == 0)
-               return 0;
-
-       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 0);
-       if (!ret) {
-               block_rsv_add_bytes(block_rsv, num_bytes, 1);
-               return 0;
-       }
-
-       return ret;
+       return __block_rsv_add(root, block_rsv, num_bytes, 0);
 }
 
 int btrfs_block_rsv_check(struct btrfs_root *root,
@@ -3851,9 +3888,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root,
        return ret;
 }
 
-int btrfs_block_rsv_refill(struct btrfs_root *root,
-                         struct btrfs_block_rsv *block_rsv,
-                         u64 min_reserved)
+static inline int __btrfs_block_rsv_refill(struct btrfs_root *root,
+                                          struct btrfs_block_rsv *block_rsv,
+                                          u64 min_reserved, int flush)
 {
        u64 num_bytes = 0;
        int ret = -ENOSPC;
@@ -3872,7 +3909,7 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
        if (!ret)
                return 0;
 
-       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 1);
+       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
        if (!ret) {
                block_rsv_add_bytes(block_rsv, num_bytes, 0);
                return 0;
@@ -3881,6 +3918,20 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
        return ret;
 }
 
+int btrfs_block_rsv_refill(struct btrfs_root *root,
+                          struct btrfs_block_rsv *block_rsv,
+                          u64 min_reserved)
+{
+       return __btrfs_block_rsv_refill(root, block_rsv, min_reserved, 1);
+}
+
+int btrfs_block_rsv_refill_noflush(struct btrfs_root *root,
+                                  struct btrfs_block_rsv *block_rsv,
+                                  u64 min_reserved)
+{
+       return __btrfs_block_rsv_refill(root, block_rsv, min_reserved, 0);
+}
+
 int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
                            struct btrfs_block_rsv *dst_rsv,
                            u64 num_bytes)
@@ -4064,23 +4115,30 @@ int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans,
  */
 static unsigned drop_outstanding_extent(struct inode *inode)
 {
+       unsigned drop_inode_space = 0;
        unsigned dropped_extents = 0;
 
        BUG_ON(!BTRFS_I(inode)->outstanding_extents);
        BTRFS_I(inode)->outstanding_extents--;
 
+       if (BTRFS_I(inode)->outstanding_extents == 0 &&
+           BTRFS_I(inode)->delalloc_meta_reserved) {
+               drop_inode_space = 1;
+               BTRFS_I(inode)->delalloc_meta_reserved = 0;
+       }
+
        /*
         * If we have more or the same amount of outsanding extents than we have
         * reserved then we need to leave the reserved extents count alone.
         */
        if (BTRFS_I(inode)->outstanding_extents >=
            BTRFS_I(inode)->reserved_extents)
-               return 0;
+               return drop_inode_space;
 
        dropped_extents = BTRFS_I(inode)->reserved_extents -
                BTRFS_I(inode)->outstanding_extents;
        BTRFS_I(inode)->reserved_extents -= dropped_extents;
-       return dropped_extents;
+       return dropped_extents + drop_inode_space;
 }
 
 /**
@@ -4166,9 +4224,18 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
                nr_extents = BTRFS_I(inode)->outstanding_extents -
                        BTRFS_I(inode)->reserved_extents;
                BTRFS_I(inode)->reserved_extents += nr_extents;
+       }
 
-               to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents);
+       /*
+        * Add an item to reserve for updating the inode when we complete the
+        * delalloc io.
+        */
+       if (!BTRFS_I(inode)->delalloc_meta_reserved) {
+               nr_extents++;
+               BTRFS_I(inode)->delalloc_meta_reserved = 1;
        }
+
+       to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents);
        to_reserve += calc_csum_metadata_size(inode, num_bytes, 1);
        spin_unlock(&BTRFS_I(inode)->lock);
 
@@ -5166,13 +5233,15 @@ search:
                }
 
 have_block_group:
-               if (unlikely(block_group->cached == BTRFS_CACHE_NO)) {
+               cached = block_group_cache_done(block_group);
+               if (unlikely(!cached)) {
                        u64 free_percent;
 
+                       found_uncached_bg = true;
                        ret = cache_block_group(block_group, trans,
                                                orig_root, 1);
                        if (block_group->cached == BTRFS_CACHE_FINISHED)
-                               goto have_block_group;
+                               goto alloc;
 
                        free_percent = btrfs_block_group_used(&block_group->item);
                        free_percent *= 100;
@@ -5194,7 +5263,6 @@ have_block_group:
                                                        orig_root, 0);
                                BUG_ON(ret);
                        }
-                       found_uncached_bg = true;
 
                        /*
                         * If loop is set for cached only, try the next block
@@ -5204,17 +5272,14 @@ have_block_group:
                                goto loop;
                }
 
-               cached = block_group_cache_done(block_group);
-               if (unlikely(!cached))
-                       found_uncached_bg = true;
-
+alloc:
                if (unlikely(block_group->ro))
                        goto loop;
 
                spin_lock(&block_group->free_space_ctl->tree_lock);
                if (cached &&
                    block_group->free_space_ctl->free_space <
-                   num_bytes + empty_size) {
+                   num_bytes + empty_cluster + empty_size) {
                        spin_unlock(&block_group->free_space_ctl->tree_lock);
                        goto loop;
                }
@@ -5235,12 +5300,10 @@ have_block_group:
                         * people trying to start a new cluster
                         */
                        spin_lock(&last_ptr->refill_lock);
-                       if (last_ptr->block_group &&
-                           (last_ptr->block_group->ro ||
-                           !block_group_bits(last_ptr->block_group, data))) {
-                               offset = 0;
+                       if (!last_ptr->block_group ||
+                           last_ptr->block_group->ro ||
+                           !block_group_bits(last_ptr->block_group, data))
                                goto refill_cluster;
-                       }
 
                        offset = btrfs_alloc_from_cluster(block_group, last_ptr,
                                                 num_bytes, search_start);
@@ -5291,7 +5354,7 @@ refill_cluster:
                        /* allocate a cluster in this block group */
                        ret = btrfs_find_space_cluster(trans, root,
                                               block_group, last_ptr,
-                                              offset, num_bytes,
+                                              search_start, num_bytes,
                                               empty_cluster + empty_size);
                        if (ret == 0) {
                                /*
index 1f87c4d0e7a072c6361fb218b32f024b111bb0a8..be1bf627a14b292655ad10a4478c015d2bff9a44 100644 (file)
@@ -2285,16 +2285,22 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                                clean_io_failure(start, page);
                }
                if (!uptodate) {
-                       u64 failed_mirror;
-                       failed_mirror = (u64)bio->bi_bdev;
-                       if (tree->ops && tree->ops->readpage_io_failed_hook)
-                               ret = tree->ops->readpage_io_failed_hook(
-                                               bio, page, start, end,
-                                               failed_mirror, state);
-                       else
-                               ret = bio_readpage_error(bio, page, start, end,
-                                                        failed_mirror, NULL);
+                       int failed_mirror;
+                       failed_mirror = (int)(unsigned long)bio->bi_bdev;
+                       /*
+                        * The generic bio_readpage_error handles errors the
+                        * following way: If possible, new read requests are
+                        * created and submitted and will end up in
+                        * end_bio_extent_readpage as well (if we're lucky, not
+                        * in the !uptodate case). In that case it returns 0 and
+                        * we just go on with the next page in our bio. If it
+                        * can't handle the error it will return -EIO and we
+                        * remain responsible for that page.
+                        */
+                       ret = bio_readpage_error(bio, page, start, end,
+                                                       failed_mirror, NULL);
                        if (ret == 0) {
+error_handled:
                                uptodate =
                                        test_bit(BIO_UPTODATE, &bio->bi_flags);
                                if (err)
@@ -2302,6 +2308,13 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                                uncache_state(&cached);
                                continue;
                        }
+                       if (tree->ops && tree->ops->readpage_io_failed_hook) {
+                               ret = tree->ops->readpage_io_failed_hook(
+                                                       bio, page, start, end,
+                                                       failed_mirror, state);
+                               if (ret == 0)
+                                       goto error_handled;
+                       }
                }
 
                if (uptodate) {
@@ -3366,6 +3379,9 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                return -ENOMEM;
        path->leave_spinning = 1;
 
+       start = ALIGN(start, BTRFS_I(inode)->root->sectorsize);
+       len = ALIGN(len, BTRFS_I(inode)->root->sectorsize);
+
        /*
         * lookup the last file extent.  We're not using i_size here
         * because there might be preallocation past i_size
@@ -3413,7 +3429,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,
                         &cached_state, GFP_NOFS);
 
-       em = get_extent_skip_holes(inode, off, last_for_get_extent,
+       em = get_extent_skip_holes(inode, start, last_for_get_extent,
                                   get_extent);
        if (!em)
                goto out;
index feb9be0e23bcca09a77497d08c74a3c8864d2a8c..7604c30013227fd823b1523503f8faaeccf283c4 100644 (file)
@@ -70,7 +70,7 @@ struct extent_io_ops {
                              unsigned long bio_flags);
        int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
        int (*readpage_io_failed_hook)(struct bio *bio, struct page *page,
-                                      u64 start, u64 end, u64 failed_mirror,
+                                      u64 start, u64 end, int failed_mirror,
                                       struct extent_state *state);
        int (*writepage_io_failed_hook)(struct bio *bio, struct page *page,
                                        u64 start, u64 end,
index 7a15fcfb3e1fb688f49d0691544a72581a328fa3..ec23d43d0c357870a14bf6e79a0ce5baeb93a43d 100644 (file)
@@ -351,6 +351,11 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode,
                }
        }
 
+       for (i = 0; i < io_ctl->num_pages; i++) {
+               clear_page_dirty_for_io(io_ctl->pages[i]);
+               set_page_extent_mapped(io_ctl->pages[i]);
+       }
+
        return 0;
 }
 
@@ -537,6 +542,13 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl,
                            struct btrfs_free_space *entry, u8 *type)
 {
        struct btrfs_free_space_entry *e;
+       int ret;
+
+       if (!io_ctl->cur) {
+               ret = io_ctl_check_crc(io_ctl, io_ctl->index);
+               if (ret)
+                       return ret;
+       }
 
        e = io_ctl->cur;
        entry->offset = le64_to_cpu(e->offset);
@@ -550,10 +562,7 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl,
 
        io_ctl_unmap_page(io_ctl);
 
-       if (io_ctl->index >= io_ctl->num_pages)
-               return 0;
-
-       return io_ctl_check_crc(io_ctl, io_ctl->index);
+       return 0;
 }
 
 static int io_ctl_read_bitmap(struct io_ctl *io_ctl,
@@ -561,9 +570,6 @@ static int io_ctl_read_bitmap(struct io_ctl *io_ctl,
 {
        int ret;
 
-       if (io_ctl->cur && io_ctl->cur != io_ctl->orig)
-               io_ctl_unmap_page(io_ctl);
-
        ret = io_ctl_check_crc(io_ctl, io_ctl->index);
        if (ret)
                return ret;
@@ -699,6 +705,8 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
                num_entries--;
        }
 
+       io_ctl_unmap_page(&io_ctl);
+
        /*
         * We add the bitmaps at the end of the entries in order that
         * the bitmap entries are added to the cache.
@@ -1462,6 +1470,7 @@ static void add_new_bitmap(struct btrfs_free_space_ctl *ctl,
 {
        info->offset = offset_to_bitmap(ctl, offset);
        info->bytes = 0;
+       INIT_LIST_HEAD(&info->list);
        link_free_space(ctl, info);
        ctl->total_bitmaps++;
 
@@ -1841,7 +1850,13 @@ again:
                info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
                                          1, 0);
                if (!info) {
-                       WARN_ON(1);
+                       /* the tree logging code might be calling us before we
+                        * have fully loaded the free space rbtree for this
+                        * block group.  So it is possible the entry won't
+                        * be in the rbtree yet at all.  The caching code
+                        * will make sure not to put it in the rbtree if
+                        * the logging code has pinned it.
+                        */
                        goto out_lock;
                }
        }
@@ -2305,6 +2320,7 @@ again:
 
        if (!found) {
                start = i;
+               cluster->max_size = 0;
                found = true;
        }
 
@@ -2448,16 +2464,23 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry;
-       struct rb_node *node;
        int ret = -ENOSPC;
+       u64 bitmap_offset = offset_to_bitmap(ctl, offset);
 
        if (ctl->total_bitmaps == 0)
                return -ENOSPC;
 
        /*
-        * First check our cached list of bitmaps and see if there is an entry
-        * here that will work.
+        * The bitmap that covers offset won't be in the list unless offset
+        * is just its start offset.
         */
+       entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
+       if (entry->offset != bitmap_offset) {
+               entry = tree_search_offset(ctl, bitmap_offset, 1, 0);
+               if (entry && list_empty(&entry->list))
+                       list_add(&entry->list, bitmaps);
+       }
+
        list_for_each_entry(entry, bitmaps, list) {
                if (entry->bytes < min_bytes)
                        continue;
@@ -2468,38 +2491,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
        }
 
        /*
-        * If we do have entries on our list and we are here then we didn't find
-        * anything, so go ahead and get the next entry after the last entry in
-        * this list and start the search from there.
+        * The bitmaps list has all the bitmaps that record free space
+        * starting after offset, so no more search is required.
         */
-       if (!list_empty(bitmaps)) {
-               entry = list_entry(bitmaps->prev, struct btrfs_free_space,
-                                  list);
-               node = rb_next(&entry->offset_index);
-               if (!node)
-                       return -ENOSPC;
-               entry = rb_entry(node, struct btrfs_free_space, offset_index);
-               goto search;
-       }
-
-       entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1);
-       if (!entry)
-               return -ENOSPC;
-
-search:
-       node = &entry->offset_index;
-       do {
-               entry = rb_entry(node, struct btrfs_free_space, offset_index);
-               node = rb_next(&entry->offset_index);
-               if (!entry->bitmap)
-                       continue;
-               if (entry->bytes < min_bytes)
-                       continue;
-               ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
-                                          bytes, min_bytes);
-       } while (ret && node);
-
-       return ret;
+       return -ENOSPC;
 }
 
 /*
@@ -2517,8 +2512,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                             u64 offset, u64 bytes, u64 empty_size)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
-       struct list_head bitmaps;
        struct btrfs_free_space *entry, *tmp;
+       LIST_HEAD(bitmaps);
        u64 min_bytes;
        int ret;
 
@@ -2557,7 +2552,6 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                goto out;
        }
 
-       INIT_LIST_HEAD(&bitmaps);
        ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,
                                      bytes, min_bytes);
        if (ret)
index 53dcbdf446cdfd859c4afe62560811081d3d1cf5..f8962a957d656b385d0f99d65f300598e419db4d 100644 (file)
@@ -398,6 +398,8 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
        struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
        struct btrfs_path *path;
        struct inode *inode;
+       struct btrfs_block_rsv *rsv;
+       u64 num_bytes;
        u64 alloc_hint = 0;
        int ret;
        int prealloc;
@@ -421,11 +423,26 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
        if (!path)
                return -ENOMEM;
 
+       rsv = trans->block_rsv;
+       trans->block_rsv = &root->fs_info->trans_block_rsv;
+
+       num_bytes = trans->bytes_reserved;
+       /*
+        * 1 item for inode item insertion if need
+        * 3 items for inode item update (in the worst case)
+        * 1 item for free space object
+        * 3 items for pre-allocation
+        */
+       trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 8);
+       ret = btrfs_block_rsv_add_noflush(root, trans->block_rsv,
+                                         trans->bytes_reserved);
+       if (ret)
+               goto out;
 again:
        inode = lookup_free_ino_inode(root, path);
        if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
                ret = PTR_ERR(inode);
-               goto out;
+               goto out_release;
        }
 
        if (IS_ERR(inode)) {
@@ -434,7 +451,7 @@ again:
 
                ret = create_free_ino_inode(root, trans, path);
                if (ret)
-                       goto out;
+                       goto out_release;
                goto again;
        }
 
@@ -477,11 +494,14 @@ again:
        }
        btrfs_free_reserved_data_space(inode, prealloc);
 
+       ret = btrfs_write_out_ino_cache(root, trans, path);
 out_put:
        iput(inode);
+out_release:
+       btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
 out:
-       if (ret == 0)
-               ret = btrfs_write_out_ino_cache(root, trans, path);
+       trans->block_rsv = rsv;
+       trans->bytes_reserved = num_bytes;
 
        btrfs_free_path(path);
        return ret;
index 966ddcc4c63d71b73be121ebd11d304d30fc723e..2c984f7d4c2ac581787ecb6a11962d3e6fd1df75 100644 (file)
@@ -93,6 +93,8 @@ static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
                                   u64 start, u64 end, int *page_started,
                                   unsigned long *nr_written, int unlock);
+static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode);
 
 static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
                                     struct inode *inode,  struct inode *dir,
@@ -1741,7 +1743,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
                                trans = btrfs_join_transaction(root);
                        BUG_ON(IS_ERR(trans));
                        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
-                       ret = btrfs_update_inode(trans, root, inode);
+                       ret = btrfs_update_inode_fallback(trans, root, inode);
                        BUG_ON(ret);
                }
                goto out;
@@ -1791,7 +1793,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
 
        ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
        if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
-               ret = btrfs_update_inode(trans, root, inode);
+               ret = btrfs_update_inode_fallback(trans, root, inode);
                BUG_ON(ret);
        }
        ret = 0;
@@ -2199,6 +2201,9 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                if (ret)
                        goto out;
        }
+       /* release the path since we're done with it */
+       btrfs_release_path(path);
+
        root->orphan_cleanup_state = ORPHAN_CLEANUP_DONE;
 
        if (root->orphan_block_rsv)
@@ -2426,7 +2431,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
 /*
  * copy everything in the in-memory inode into the btree.
  */
-noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
+static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root, struct inode *inode)
 {
        struct btrfs_inode_item *inode_item;
@@ -2434,21 +2439,6 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
        struct extent_buffer *leaf;
        int ret;
 
-       /*
-        * If the inode is a free space inode, we can deadlock during commit
-        * if we put it into the delayed code.
-        *
-        * The data relocation inode should also be directly updated
-        * without delay
-        */
-       if (!btrfs_is_free_space_inode(root, inode)
-           && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
-               ret = btrfs_delayed_update_inode(trans, root, inode);
-               if (!ret)
-                       btrfs_set_inode_last_trans(trans, inode);
-               return ret;
-       }
-
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -2476,6 +2466,43 @@ failed:
        return ret;
 }
 
+/*
+ * copy everything in the in-memory inode into the btree.
+ */
+noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode)
+{
+       int ret;
+
+       /*
+        * If the inode is a free space inode, we can deadlock during commit
+        * if we put it into the delayed code.
+        *
+        * The data relocation inode should also be directly updated
+        * without delay
+        */
+       if (!btrfs_is_free_space_inode(root, inode)
+           && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
+               ret = btrfs_delayed_update_inode(trans, root, inode);
+               if (!ret)
+                       btrfs_set_inode_last_trans(trans, inode);
+               return ret;
+       }
+
+       return btrfs_update_inode_item(trans, root, inode);
+}
+
+static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode)
+{
+       int ret;
+
+       ret = btrfs_update_inode(trans, root, inode);
+       if (ret == -ENOSPC)
+               return btrfs_update_inode_item(trans, root, inode);
+       return ret;
+}
+
 /*
  * unlink helper that gets used here in inode.c and in the tree logging
  * recovery code.  It remove a link in a directory with a given name, and
@@ -3463,7 +3490,7 @@ void btrfs_evict_inode(struct inode *inode)
         * doing the truncate.
         */
        while (1) {
-               ret = btrfs_block_rsv_refill(root, rsv, min_size);
+               ret = btrfs_block_rsv_refill_noflush(root, rsv, min_size);
 
                /*
                 * Try and steal from the global reserve since we will
@@ -5632,7 +5659,7 @@ again:
        if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) {
                ret = btrfs_ordered_update_i_size(inode, 0, ordered);
                if (!ret)
-                       err = btrfs_update_inode(trans, root, inode);
+                       err = btrfs_update_inode_fallback(trans, root, inode);
                goto out;
        }
 
@@ -5670,7 +5697,7 @@ again:
        add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
        ret = btrfs_ordered_update_i_size(inode, 0, ordered);
        if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags))
-               btrfs_update_inode(trans, root, inode);
+               btrfs_update_inode_fallback(trans, root, inode);
        ret = 0;
 out_unlock:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset,
@@ -6529,14 +6556,16 @@ end_trans:
                ret = btrfs_orphan_del(NULL, inode);
        }
 
-       trans->block_rsv = &root->fs_info->trans_block_rsv;
-       ret = btrfs_update_inode(trans, root, inode);
-       if (ret && !err)
-               err = ret;
+       if (trans) {
+               trans->block_rsv = &root->fs_info->trans_block_rsv;
+               ret = btrfs_update_inode(trans, root, inode);
+               if (ret && !err)
+                       err = ret;
 
-       nr = trans->blocks_used;
-       ret = btrfs_end_transaction_throttle(trans, root);
-       btrfs_btree_balance_dirty(root, nr);
+               nr = trans->blocks_used;
+               ret = btrfs_end_transaction_throttle(trans, root);
+               btrfs_btree_balance_dirty(root, nr);
+       }
 
 out:
        btrfs_free_block_rsv(root, rsv);
@@ -6605,6 +6634,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        ei->orphan_meta_reserved = 0;
        ei->dummy_inode = 0;
        ei->in_defrag = 0;
+       ei->delalloc_meta_reserved = 0;
        ei->force_compress = BTRFS_COMPRESS_NONE;
 
        ei->delayed_node = NULL;
@@ -6764,11 +6794,13 @@ static int btrfs_getattr(struct vfsmount *mnt,
                         struct dentry *dentry, struct kstat *stat)
 {
        struct inode *inode = dentry->d_inode;
+       u32 blocksize = inode->i_sb->s_blocksize;
+
        generic_fillattr(inode, stat);
        stat->dev = BTRFS_I(inode)->root->anon_dev;
        stat->blksize = PAGE_CACHE_SIZE;
-       stat->blocks = (inode_get_bytes(inode) +
-                       BTRFS_I(inode)->delalloc_bytes) >> 9;
+       stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) +
+               ALIGN(BTRFS_I(inode)->delalloc_bytes, blocksize)) >> 9;
        return 0;
 }
 
index 4a34c472f1261bea0c3c228e9800d04a26a6d714..72d461656f606647292657f2367ee438a50d2a40 100644 (file)
@@ -1216,12 +1216,12 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
                *devstr = '\0';
                devstr = vol_args->name;
                devid = simple_strtoull(devstr, &end, 10);
-               printk(KERN_INFO "resizing devid %llu\n",
+               printk(KERN_INFO "btrfs: resizing devid %llu\n",
                       (unsigned long long)devid);
        }
        device = btrfs_find_device(root, devid, NULL, NULL);
        if (!device) {
-               printk(KERN_INFO "resizer unable to find device %llu\n",
+               printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",
                       (unsigned long long)devid);
                ret = -EINVAL;
                goto out_unlock;
@@ -1267,7 +1267,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
        do_div(new_size, root->sectorsize);
        new_size *= root->sectorsize;
 
-       printk(KERN_INFO "new size for %s is %llu\n",
+       printk(KERN_INFO "btrfs: new size for %s is %llu\n",
                device->name, (unsigned long long)new_size);
 
        if (new_size > old_size) {
@@ -1278,7 +1278,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
                }
                ret = btrfs_grow_device(trans, device, new_size);
                btrfs_commit_transaction(trans, root);
-       } else {
+       } else if (new_size < old_size) {
                ret = btrfs_shrink_device(device, new_size);
        }
 
@@ -2930,11 +2930,13 @@ static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
                goto out;
 
        for (i = 0; i < ipath->fspath->elem_cnt; ++i) {
-               rel_ptr = ipath->fspath->val[i] - (u64)ipath->fspath->val;
+               rel_ptr = ipath->fspath->val[i] -
+                         (u64)(unsigned long)ipath->fspath->val;
                ipath->fspath->val[i] = rel_ptr;
        }
 
-       ret = copy_to_user((void *)ipa->fspath, (void *)ipath->fspath, size);
+       ret = copy_to_user((void *)(unsigned long)ipa->fspath,
+                          (void *)(unsigned long)ipath->fspath, size);
        if (ret) {
                ret = -EFAULT;
                goto out;
@@ -3017,7 +3019,8 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
        if (ret < 0)
                goto out;
 
-       ret = copy_to_user((void *)loi->inodes, (void *)inodes, size);
+       ret = copy_to_user((void *)(unsigned long)loi->inodes,
+                          (void *)(unsigned long)inodes, size);
        if (ret)
                ret = -EFAULT;
 
index 24d654ce7a061206347173c407196fdcf0bc8742..dff29d5e151a3b80d516be44cc1ebdf0d00adad6 100644 (file)
@@ -1174,6 +1174,8 @@ static int clone_backref_node(struct btrfs_trans_handle *trans,
                        list_add_tail(&new_edge->list[UPPER],
                                      &new_node->lower);
                }
+       } else {
+               list_add_tail(&new_node->lower, &cache->leaves);
        }
 
        rb_node = tree_insert(&cache->rb_root, new_node->bytenr,
index ed11d3866afde2ccef62ab55f66374622cb649fe..c27bcb67f3304d806ab7e90cef8c3bcdef78b19c 100644 (file)
@@ -256,6 +256,11 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx)
        btrfs_release_path(swarn->path);
 
        ipath = init_ipath(4096, local_root, swarn->path);
+       if (IS_ERR(ipath)) {
+               ret = PTR_ERR(ipath);
+               ipath = NULL;
+               goto err;
+       }
        ret = paths_from_inode(inum, ipath);
 
        if (ret < 0)
@@ -272,7 +277,7 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx)
                        swarn->logical, swarn->dev->name,
                        (unsigned long long)swarn->sector, root, inum, offset,
                        min(isize - offset, (u64)PAGE_SIZE), nlink,
-                       (char *)ipath->fspath->val[i]);
+                       (char *)(unsigned long)ipath->fspath->val[i]);
 
        free_ipath(ipath);
        return 0;
@@ -944,50 +949,18 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer)
 static int scrub_submit(struct scrub_dev *sdev)
 {
        struct scrub_bio *sbio;
-       struct bio *bio;
-       int i;
 
        if (sdev->curr == -1)
                return 0;
 
        sbio = sdev->bios[sdev->curr];
-
-       bio = bio_alloc(GFP_NOFS, sbio->count);
-       if (!bio)
-               goto nomem;
-
-       bio->bi_private = sbio;
-       bio->bi_end_io = scrub_bio_end_io;
-       bio->bi_bdev = sdev->dev->bdev;
-       bio->bi_sector = sbio->physical >> 9;
-
-       for (i = 0; i < sbio->count; ++i) {
-               struct page *page;
-               int ret;
-
-               page = alloc_page(GFP_NOFS);
-               if (!page)
-                       goto nomem;
-
-               ret = bio_add_page(bio, page, PAGE_SIZE, 0);
-               if (!ret) {
-                       __free_page(page);
-                       goto nomem;
-               }
-       }
-
        sbio->err = 0;
        sdev->curr = -1;
        atomic_inc(&sdev->in_flight);
 
-       submit_bio(READ, bio);
+       submit_bio(READ, sbio->bio);
 
        return 0;
-
-nomem:
-       scrub_free_bio(bio);
-
-       return -ENOMEM;
 }
 
 static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len,
@@ -995,6 +968,8 @@ static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len,
                      u8 *csum, int force)
 {
        struct scrub_bio *sbio;
+       struct page *page;
+       int ret;
 
 again:
        /*
@@ -1015,12 +990,22 @@ again:
        }
        sbio = sdev->bios[sdev->curr];
        if (sbio->count == 0) {
+               struct bio *bio;
+
                sbio->physical = physical;
                sbio->logical = logical;
+               bio = bio_alloc(GFP_NOFS, SCRUB_PAGES_PER_BIO);
+               if (!bio)
+                       return -ENOMEM;
+
+               bio->bi_private = sbio;
+               bio->bi_end_io = scrub_bio_end_io;
+               bio->bi_bdev = sdev->dev->bdev;
+               bio->bi_sector = sbio->physical >> 9;
+               sbio->err = 0;
+               sbio->bio = bio;
        } else if (sbio->physical + sbio->count * PAGE_SIZE != physical ||
                   sbio->logical + sbio->count * PAGE_SIZE != logical) {
-               int ret;
-
                ret = scrub_submit(sdev);
                if (ret)
                        return ret;
@@ -1030,6 +1015,20 @@ again:
        sbio->spag[sbio->count].generation = gen;
        sbio->spag[sbio->count].have_csum = 0;
        sbio->spag[sbio->count].mirror_num = mirror_num;
+
+       page = alloc_page(GFP_NOFS);
+       if (!page)
+               return -ENOMEM;
+
+       ret = bio_add_page(sbio->bio, page, PAGE_SIZE, 0);
+       if (!ret) {
+               __free_page(page);
+               ret = scrub_submit(sdev);
+               if (ret)
+                       return ret;
+               goto again;
+       }
+
        if (csum) {
                sbio->spag[sbio->count].have_csum = 1;
                memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size);
index 57080dffdfc6f101246dfa222f26ecfdc6f4b818..e28ad4baf483af6b4c7e5d8450dc4a73909d0247 100644 (file)
@@ -197,7 +197,7 @@ static match_table_t tokens = {
        {Opt_subvolrootid, "subvolrootid=%d"},
        {Opt_defrag, "autodefrag"},
        {Opt_inode_cache, "inode_cache"},
-       {Opt_no_space_cache, "no_space_cache"},
+       {Opt_no_space_cache, "nospace_cache"},
        {Opt_recovery, "recovery"},
        {Opt_err, NULL},
 };
@@ -448,6 +448,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
                token = match_token(p, tokens, args);
                switch (token) {
                case Opt_subvol:
+                       kfree(*subvol_name);
                        *subvol_name = match_strdup(&args[0]);
                        break;
                case Opt_subvolid:
@@ -710,7 +711,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
        if (btrfs_test_opt(root, SPACE_CACHE))
                seq_puts(seq, ",space_cache");
        else
-               seq_puts(seq, ",no_space_cache");
+               seq_puts(seq, ",nospace_cache");
        if (btrfs_test_opt(root, CLEAR_CACHE))
                seq_puts(seq, ",clear_cache");
        if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED))
@@ -824,13 +825,9 @@ static char *setup_root_args(char *args)
 static struct dentry *mount_subvol(const char *subvol_name, int flags,
                                   const char *device_name, char *data)
 {
-       struct super_block *s;
        struct dentry *root;
        struct vfsmount *mnt;
-       struct mnt_namespace *ns_private;
        char *newargs;
-       struct path path;
-       int error;
 
        newargs = setup_root_args(data);
        if (!newargs)
@@ -841,39 +838,17 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
        if (IS_ERR(mnt))
                return ERR_CAST(mnt);
 
-       ns_private = create_mnt_ns(mnt);
-       if (IS_ERR(ns_private)) {
-               mntput(mnt);
-               return ERR_CAST(ns_private);
-       }
-
-       /*
-        * This will trigger the automount of the subvol so we can just
-        * drop the mnt we have here and return the dentry that we
-        * found.
-        */
-       error = vfs_path_lookup(mnt->mnt_root, mnt, subvol_name,
-                               LOOKUP_FOLLOW, &path);
-       put_mnt_ns(ns_private);
-       if (error)
-               return ERR_PTR(error);
+       root = mount_subtree(mnt, subvol_name);
 
-       if (!is_subvolume_inode(path.dentry->d_inode)) {
-               path_put(&path);
-               mntput(mnt);
-               error = -EINVAL;
+       if (!IS_ERR(root) && !is_subvolume_inode(root->d_inode)) {
+               struct super_block *s = root->d_sb;
+               dput(root);
+               root = ERR_PTR(-EINVAL);
+               deactivate_locked_super(s);
                printk(KERN_ERR "btrfs: '%s' is not a valid subvolume\n",
                                subvol_name);
-               return ERR_PTR(-EINVAL);
        }
 
-       /* Get a ref to the sb and the dentry we found and return it */
-       s = path.mnt->mnt_sb;
-       atomic_inc(&s->s_active);
-       root = dget(path.dentry);
-       path_put(&path);
-       down_write(&s->s_umount);
-
        return root;
 }
 
@@ -890,7 +865,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        struct super_block *s;
        struct dentry *root;
        struct btrfs_fs_devices *fs_devices = NULL;
-       struct btrfs_root *tree_root = NULL;
        struct btrfs_fs_info *fs_info = NULL;
        fmode_t mode = FMODE_READ;
        char *subvol_name = NULL;
@@ -904,8 +878,10 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        error = btrfs_parse_early_options(data, mode, fs_type,
                                          &subvol_name, &subvol_objectid,
                                          &subvol_rootid, &fs_devices);
-       if (error)
+       if (error) {
+               kfree(subvol_name);
                return ERR_PTR(error);
+       }
 
        if (subvol_name) {
                root = mount_subvol(subvol_name, flags, device_name, data);
@@ -917,15 +893,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        if (error)
                return ERR_PTR(error);
 
-       error = btrfs_open_devices(fs_devices, mode, fs_type);
-       if (error)
-               return ERR_PTR(error);
-
-       if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
-               error = -EACCES;
-               goto error_close_devices;
-       }
-
        /*
         * Setup a dummy root and fs_info for test/set super.  This is because
         * we don't actually fill this stuff out until open_ctree, but we need
@@ -933,24 +900,36 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
         * then open_ctree will properly initialize everything later.
         */
        fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS);
-       tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
-       if (!fs_info || !tree_root) {
+       if (!fs_info)
+               return ERR_PTR(-ENOMEM);
+
+       fs_info->tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       if (!fs_info->tree_root) {
                error = -ENOMEM;
-               goto error_close_devices;
+               goto error_fs_info;
        }
-       fs_info->tree_root = tree_root;
+       fs_info->tree_root->fs_info = fs_info;
        fs_info->fs_devices = fs_devices;
-       tree_root->fs_info = fs_info;
 
        fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
        fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
        if (!fs_info->super_copy || !fs_info->super_for_commit) {
                error = -ENOMEM;
+               goto error_fs_info;
+       }
+
+       error = btrfs_open_devices(fs_devices, mode, fs_type);
+       if (error)
+               goto error_fs_info;
+
+       if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
+               error = -EACCES;
                goto error_close_devices;
        }
 
        bdev = fs_devices->latest_bdev;
-       s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root);
+       s = sget(fs_type, btrfs_test_super, btrfs_set_super,
+                fs_info->tree_root);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto error_close_devices;
@@ -959,12 +938,12 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        if (s->s_root) {
                if ((flags ^ s->s_flags) & MS_RDONLY) {
                        deactivate_locked_super(s);
-                       return ERR_PTR(-EBUSY);
+                       error = -EBUSY;
+                       goto error_close_devices;
                }
 
                btrfs_close_devices(fs_devices);
                free_fs_info(fs_info);
-               kfree(tree_root);
        } else {
                char b[BDEVNAME_SIZE];
 
@@ -991,8 +970,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
 
 error_close_devices:
        btrfs_close_devices(fs_devices);
+error_fs_info:
        free_fs_info(fs_info);
-       kfree(tree_root);
        return ERR_PTR(error);
 }
 
@@ -1078,7 +1057,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
        int i = 0, nr_devices;
        int ret;
 
-       nr_devices = fs_info->fs_devices->rw_devices;
+       nr_devices = fs_info->fs_devices->open_devices;
        BUG_ON(!nr_devices);
 
        devices_info = kmalloc(sizeof(*devices_info) * nr_devices,
@@ -1100,8 +1079,8 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
        else
                min_stripe_size = BTRFS_STRIPE_LEN;
 
-       list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
-               if (!device->in_fs_metadata)
+       list_for_each_entry(device, &fs_devices->devices, dev_list) {
+               if (!device->in_fs_metadata || !device->bdev)
                        continue;
 
                avail_space = device->total_bytes - device->bytes_used;
index 960835eaf4da7acfd4b9f3f11dd0fb16f811b007..81376d94cd3c6a4639ebef35df501dbefbfb2435 100644 (file)
@@ -785,6 +785,10 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
 
                        btrfs_save_ino_cache(root, trans);
 
+                       /* see comments in should_cow_block() */
+                       root->force_cow = 0;
+                       smp_wmb();
+
                        if (root->commit_root != root->node) {
                                mutex_lock(&root->fs_commit_mutex);
                                switch_commit_root(root);
@@ -882,8 +886,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_reloc_pre_snapshot(trans, pending, &to_reserve);
 
        if (to_reserve > 0) {
-               ret = btrfs_block_rsv_add(root, &pending->block_rsv,
-                                         to_reserve);
+               ret = btrfs_block_rsv_add_noflush(root, &pending->block_rsv,
+                                                 to_reserve);
                if (ret) {
                        pending->error = ret;
                        goto fail;
@@ -947,6 +951,10 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_tree_unlock(old);
        free_extent_buffer(old);
 
+       /* see comments in should_cow_block() */
+       root->force_cow = 1;
+       smp_wmb();
+
        btrfs_set_root_node(new_root_item, tmp);
        /* record when the snapshot was created in key.offset */
        key.offset = trans->transid;
index f8e2943101a11b43efeac758643d54e85abb9ee4..c37433d3cd82464adbe13173433521a4ab1cca14 100644 (file)
@@ -999,7 +999,7 @@ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
        key.objectid = device->devid;
        key.offset = start;
        key.type = BTRFS_DEV_EXTENT_KEY;
-
+again:
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret > 0) {
                ret = btrfs_previous_item(root, path, key.objectid,
@@ -1012,6 +1012,9 @@ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
                                        struct btrfs_dev_extent);
                BUG_ON(found_key.offset > start || found_key.offset +
                       btrfs_dev_extent_length(leaf, extent) < start);
+               key = found_key;
+               btrfs_release_path(path);
+               goto again;
        } else if (ret == 0) {
                leaf = path->nodes[0];
                extent = btrfs_item_ptr(leaf, path->slots[0],
index ab5b1c49f3529e9e7e112649b98f22d0a923fb35..78f2d4d4f37fe81317395688a8b090b71e53a612 100644 (file)
@@ -100,6 +100,12 @@ struct btrfs_device {
        struct reada_zone *reada_curr_zone;
        struct radix_tree_root reada_zones;
        struct radix_tree_root reada_extents;
+
+       /* for sending down flush barriers */
+       struct bio *flush_bio;
+       struct completion flush_wait;
+       int nobarriers;
+
 };
 
 struct btrfs_fs_devices {
index 2abd0dfad7f8093c252e572d90fdd42991b410be..bca3948e9dbf6758746c896359471f4730407e24 100644 (file)
@@ -1143,7 +1143,7 @@ static void ceph_d_prune(struct dentry *dentry)
 {
        struct ceph_dentry_info *di;
 
-       dout("d_release %p\n", dentry);
+       dout("ceph_d_prune %p\n", dentry);
 
        /* do we have a valid parent? */
        if (!dentry->d_parent || IS_ROOT(dentry))
index e392bfce84a3cc6873f1439ba8dd5f28fd0cd935..116f36502f178f5ce0475bdfdd77073e9452e614 100644 (file)
@@ -1328,12 +1328,13 @@ int ceph_inode_set_size(struct inode *inode, loff_t size)
  */
 void ceph_queue_writeback(struct inode *inode)
 {
+       ihold(inode);
        if (queue_work(ceph_inode_to_client(inode)->wb_wq,
                       &ceph_inode(inode)->i_wb_work)) {
                dout("ceph_queue_writeback %p\n", inode);
-               ihold(inode);
        } else {
                dout("ceph_queue_writeback %p failed\n", inode);
+               iput(inode);
        }
 }
 
@@ -1353,12 +1354,13 @@ static void ceph_writeback_work(struct work_struct *work)
  */
 void ceph_queue_invalidate(struct inode *inode)
 {
+       ihold(inode);
        if (queue_work(ceph_inode_to_client(inode)->pg_inv_wq,
                       &ceph_inode(inode)->i_pg_inv_work)) {
                dout("ceph_queue_invalidate %p\n", inode);
-               ihold(inode);
        } else {
                dout("ceph_queue_invalidate %p failed\n", inode);
+               iput(inode);
        }
 }
 
@@ -1434,13 +1436,14 @@ void ceph_queue_vmtruncate(struct inode *inode)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
 
+       ihold(inode);
        if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq,
                       &ci->i_vmtruncate_work)) {
                dout("ceph_queue_vmtruncate %p\n", inode);
-               ihold(inode);
        } else {
                dout("ceph_queue_vmtruncate %p failed, pending=%d\n",
                     inode, ci->i_truncate_pending);
+               iput(inode);
        }
 }
 
index a90846fac759bd744620a8d87789e9a56db02c48..8dc73a594a90c11e31f20ef925104ea10e5b0b15 100644 (file)
@@ -638,10 +638,12 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
        if (err == 0) {
                dout("open_root_inode success\n");
                if (ceph_ino(req->r_target_inode) == CEPH_INO_ROOT &&
-                   fsc->sb->s_root == NULL)
+                   fsc->sb->s_root == NULL) {
                        root = d_alloc_root(req->r_target_inode);
-               else
+                       ceph_init_dentry(root);
+               } else {
                        root = d_obtain_alias(req->r_target_inode);
+               }
                req->r_target_inode = NULL;
                dout("open_root_inode success, root dentry is %p\n", root);
        } else {
index c1f063cd1b0cf2cd5d8d957a4a65f75b61a4c42a..cf0b1539b321acf1cdd69e4db0f590d8f83e9293 100644 (file)
@@ -645,20 +645,20 @@ int cifs_closedir(struct inode *inode, struct file *file)
 }
 
 static struct cifsLockInfo *
-cifs_lock_init(__u64 len, __u64 offset, __u8 type, __u16 netfid)
+cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid)
 {
-       struct cifsLockInfo *li =
+       struct cifsLockInfo *lock =
                kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
-       if (!li)
-               return li;
-       li->netfid = netfid;
-       li->offset = offset;
-       li->length = len;
-       li->type = type;
-       li->pid = current->tgid;
-       INIT_LIST_HEAD(&li->blist);
-       init_waitqueue_head(&li->block_q);
-       return li;
+       if (!lock)
+               return lock;
+       lock->offset = offset;
+       lock->length = length;
+       lock->type = type;
+       lock->netfid = netfid;
+       lock->pid = current->tgid;
+       INIT_LIST_HEAD(&lock->blist);
+       init_waitqueue_head(&lock->block_q);
+       return lock;
 }
 
 static void
@@ -672,7 +672,7 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock)
 }
 
 static bool
-cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
+__cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
                        __u64 length, __u8 type, __u16 netfid,
                        struct cifsLockInfo **conf_lock)
 {
@@ -694,6 +694,14 @@ cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
        return false;
 }
 
+static bool
+cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock,
+                       struct cifsLockInfo **conf_lock)
+{
+       return __cifs_find_lock_conflict(cinode, lock->offset, lock->length,
+                                        lock->type, lock->netfid, conf_lock);
+}
+
 static int
 cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
               __u8 type, __u16 netfid, struct file_lock *flock)
@@ -704,8 +712,8 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
 
        mutex_lock(&cinode->lock_mutex);
 
-       exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid,
-                                       &conf_lock);
+       exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid,
+                                         &conf_lock);
        if (exist) {
                flock->fl_start = conf_lock->offset;
                flock->fl_end = conf_lock->offset + conf_lock->length - 1;
@@ -723,40 +731,27 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
        return rc;
 }
 
-static int
-cifs_lock_add(struct cifsInodeInfo *cinode, __u64 len, __u64 offset,
-             __u8 type, __u16 netfid)
+static void
+cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock)
 {
-       struct cifsLockInfo *li;
-
-       li = cifs_lock_init(len, offset, type, netfid);
-       if (!li)
-               return -ENOMEM;
-
        mutex_lock(&cinode->lock_mutex);
-       list_add_tail(&li->llist, &cinode->llist);
+       list_add_tail(&lock->llist, &cinode->llist);
        mutex_unlock(&cinode->lock_mutex);
-       return 0;
 }
 
 static int
-cifs_lock_add_if(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
-                __u8 type, __u16 netfid, bool wait)
+cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock,
+                bool wait)
 {
-       struct cifsLockInfo *lock, *conf_lock;
+       struct cifsLockInfo *conf_lock;
        bool exist;
        int rc = 0;
 
-       lock = cifs_lock_init(length, offset, type, netfid);
-       if (!lock)
-               return -ENOMEM;
-
 try_again:
        exist = false;
        mutex_lock(&cinode->lock_mutex);
 
-       exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid,
-                                       &conf_lock);
+       exist = cifs_find_lock_conflict(cinode, lock, &conf_lock);
        if (!exist && cinode->can_cache_brlcks) {
                list_add_tail(&lock->llist, &cinode->llist);
                mutex_unlock(&cinode->lock_mutex);
@@ -775,13 +770,10 @@ try_again:
                                        (lock->blist.next == &lock->blist));
                if (!rc)
                        goto try_again;
-               else {
-                       mutex_lock(&cinode->lock_mutex);
-                       list_del_init(&lock->blist);
-               }
+               mutex_lock(&cinode->lock_mutex);
+               list_del_init(&lock->blist);
        }
 
-       kfree(lock);
        mutex_unlock(&cinode->lock_mutex);
        return rc;
 }
@@ -933,7 +925,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
                else
                        type = CIFS_WRLCK;
 
-               lck = cifs_lock_init(length, flock->fl_start, type,
+               lck = cifs_lock_init(flock->fl_start, length, type,
                                     cfile->netfid);
                if (!lck) {
                        rc = -ENOMEM;
@@ -1070,14 +1062,12 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type,
                if (rc != 0)
                        cERROR(1, "Error unlocking previously locked "
                                   "range %d during test of lock", rc);
-               rc = 0;
-               return rc;
+               return 0;
        }
 
        if (type & LOCKING_ANDX_SHARED_LOCK) {
                flock->fl_type = F_WRLCK;
-               rc = 0;
-               return rc;
+               return 0;
        }
 
        rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
@@ -1095,8 +1085,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type,
        } else
                flock->fl_type = F_WRLCK;
 
-       rc = 0;
-       return rc;
+       return 0;
 }
 
 static void
@@ -1254,20 +1243,26 @@ cifs_setlk(struct file *file,  struct file_lock *flock, __u8 type,
        }
 
        if (lock) {
-               rc = cifs_lock_add_if(cinode, flock->fl_start, length,
-                                     type, netfid, wait_flag);
+               struct cifsLockInfo *lock;
+
+               lock = cifs_lock_init(flock->fl_start, length, type, netfid);
+               if (!lock)
+                       return -ENOMEM;
+
+               rc = cifs_lock_add_if(cinode, lock, wait_flag);
                if (rc < 0)
-                       return rc;
-               else if (!rc)
+                       kfree(lock);
+               if (rc <= 0)
                        goto out;
 
                rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
                                 flock->fl_start, 0, 1, type, wait_flag, 0);
-               if (rc == 0) {
-                       /* For Windows locks we must store them. */
-                       rc = cifs_lock_add(cinode, length, flock->fl_start,
-                                          type, netfid);
+               if (rc) {
+                       kfree(lock);
+                       goto out;
                }
+
+               cifs_lock_add(cinode, lock);
        } else if (unlock)
                rc = cifs_unlock_range(cfile, flock, xid);
 
index 274f13e2f0946ed66ac186833efa1898b84db3fa..10ba92def3f675985871f0fc72e9c6d7126357a3 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/bit_spinlock.h>
 #include <linux/rculist_bl.h>
 #include <linux/prefetch.h>
+#include <linux/ratelimit.h>
 #include "internal.h"
 
 /*
@@ -546,9 +547,11 @@ int d_invalidate(struct dentry * dentry)
         * would make it unreachable from the root,
         * we might still populate it if it was a
         * working directory or similar).
+        * We also need to leave mountpoints alone,
+        * directory or not.
         */
-       if (dentry->d_count > 1) {
-               if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
+       if (dentry->d_count > 1 && dentry->d_inode) {
+               if (S_ISDIR(dentry->d_inode->i_mode) || d_mountpoint(dentry)) {
                        spin_unlock(&dentry->d_lock);
                        return -EBUSY;
                }
@@ -2381,8 +2384,16 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
                                actual = __d_unalias(inode, dentry, alias);
                        }
                        write_sequnlock(&rename_lock);
-                       if (IS_ERR(actual))
+                       if (IS_ERR(actual)) {
+                               if (PTR_ERR(actual) == -ELOOP)
+                                       pr_warn_ratelimited(
+                                               "VFS: Lookup of '%s' in %s %s"
+                                               " would have caused loop\n",
+                                               dentry->d_name.name,
+                                               inode->i_sb->s_type->name,
+                                               inode->i_sb->s_id);
                                dput(alias);
+                       }
                        goto out_nolock;
                }
        }
index 58609bde3b9fc076187afa3317582788f2f6bc7f..2a834255c75de911b7e1f8eb10026972913e14b4 100644 (file)
@@ -967,7 +967,7 @@ static void ecryptfs_set_default_crypt_stat_vals(
 
 /**
  * ecryptfs_new_file_context
- * @ecryptfs_dentry: The eCryptfs dentry
+ * @ecryptfs_inode: The eCryptfs inode
  *
  * If the crypto context for the file has not yet been established,
  * this is where we do that.  Establishing a new crypto context
@@ -984,13 +984,13 @@ static void ecryptfs_set_default_crypt_stat_vals(
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry)
+int ecryptfs_new_file_context(struct inode *ecryptfs_inode)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
-           &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+           &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
            &ecryptfs_superblock_to_private(
-                   ecryptfs_dentry->d_sb)->mount_crypt_stat;
+                   ecryptfs_inode->i_sb)->mount_crypt_stat;
        int cipher_name_len;
        int rc = 0;
 
@@ -1299,12 +1299,12 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t max,
 }
 
 static int
-ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry,
+ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode,
                                    char *virt, size_t virt_len)
 {
        int rc;
 
-       rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
+       rc = ecryptfs_write_lower(ecryptfs_inode, virt,
                                  0, virt_len);
        if (rc < 0)
                printk(KERN_ERR "%s: Error attempting to write header "
@@ -1338,7 +1338,8 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask,
 
 /**
  * ecryptfs_write_metadata
- * @ecryptfs_dentry: The eCryptfs dentry
+ * @ecryptfs_dentry: The eCryptfs dentry, which should be negative
+ * @ecryptfs_inode: The newly created eCryptfs inode
  *
  * Write the file headers out.  This will likely involve a userspace
  * callout, in which the session key is encrypted with one or more
@@ -1348,10 +1349,11 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask,
  *
  * Returns zero on success; non-zero on error
  */
-int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+                           struct inode *ecryptfs_inode)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
-               &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+               &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        unsigned int order;
        char *virt;
        size_t virt_len;
@@ -1391,7 +1393,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
                rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt,
                                                      size);
        else
-               rc = ecryptfs_write_metadata_to_contents(ecryptfs_dentry, virt,
+               rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt,
                                                         virt_len);
        if (rc) {
                printk(KERN_ERR "%s: Error writing metadata out to lower file; "
@@ -1943,7 +1945,7 @@ static unsigned char *portable_filename_chars = ("-.0123456789ABCD"
 
 /* We could either offset on every reverse map or just pad some 0x00's
  * at the front here */
-static const unsigned char filename_rev_map[] = {
+static const unsigned char filename_rev_map[256] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */
@@ -1959,7 +1961,7 @@ static const unsigned char filename_rev_map[] = {
        0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */
        0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */
        0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */
-       0x3D, 0x3E, 0x3F
+       0x3D, 0x3E, 0x3F /* 123 - 255 initialized to 0x00 */
 };
 
 /**
index 54481a3b2c7960e6ba205696c9d69ec44b331194..a9f29b12fbf290ba4987f778e582357d38ae1258 100644 (file)
@@ -584,9 +584,10 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat);
 int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode);
 int ecryptfs_encrypt_page(struct page *page);
 int ecryptfs_decrypt_page(struct page *page);
-int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry);
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+                           struct inode *ecryptfs_inode);
 int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry);
-int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry);
+int ecryptfs_new_file_context(struct inode *ecryptfs_inode);
 void ecryptfs_write_crypt_stat_flags(char *page_virt,
                                     struct ecryptfs_crypt_stat *crypt_stat,
                                     size_t *written);
index c6ac98cf9baaeca5d898cce216aa0dc08df2716c..d3f95f941c47e68a1d0a2cbe60371f148d64e124 100644 (file)
@@ -139,6 +139,27 @@ out:
        return rc;
 }
 
+static void ecryptfs_vma_close(struct vm_area_struct *vma)
+{
+       filemap_write_and_wait(vma->vm_file->f_mapping);
+}
+
+static const struct vm_operations_struct ecryptfs_file_vm_ops = {
+       .close          = ecryptfs_vma_close,
+       .fault          = filemap_fault,
+};
+
+static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       int rc;
+
+       rc = generic_file_mmap(file, vma);
+       if (!rc)
+               vma->vm_ops = &ecryptfs_file_vm_ops;
+
+       return rc;
+}
+
 struct kmem_cache *ecryptfs_file_info_cache;
 
 /**
@@ -349,7 +370,7 @@ const struct file_operations ecryptfs_main_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl = ecryptfs_compat_ioctl,
 #endif
-       .mmap = generic_file_mmap,
+       .mmap = ecryptfs_file_mmap,
        .open = ecryptfs_open,
        .flush = ecryptfs_flush,
        .release = ecryptfs_release,
index a36d327f15215e471628e2fda253e84ccd6100e9..32f90a3ae63eb85bc6d162aa16f28d48b3cdac7f 100644 (file)
@@ -172,22 +172,23 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode,
  * it. It will also update the eCryptfs directory inode to mimic the
  * stat of the lower directory inode.
  *
- * Returns zero on success; non-zero on error condition
+ * Returns the new eCryptfs inode on success; an ERR_PTR on error condition
  */
-static int
+static struct inode *
 ecryptfs_do_create(struct inode *directory_inode,
                   struct dentry *ecryptfs_dentry, int mode)
 {
        int rc;
        struct dentry *lower_dentry;
        struct dentry *lower_dir_dentry;
+       struct inode *inode;
 
        lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
        if (IS_ERR(lower_dir_dentry)) {
                ecryptfs_printk(KERN_ERR, "Error locking directory of "
                                "dentry\n");
-               rc = PTR_ERR(lower_dir_dentry);
+               inode = ERR_CAST(lower_dir_dentry);
                goto out;
        }
        rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
@@ -195,20 +196,19 @@ ecryptfs_do_create(struct inode *directory_inode,
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
                       "rc = [%d]\n", __func__, rc);
+               inode = ERR_PTR(rc);
                goto out_lock;
        }
-       rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
-                               directory_inode->i_sb);
-       if (rc) {
-               ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n");
+       inode = __ecryptfs_get_inode(lower_dentry->d_inode,
+                                    directory_inode->i_sb);
+       if (IS_ERR(inode))
                goto out_lock;
-       }
        fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
        fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
 out_lock:
        unlock_dir(lower_dir_dentry);
 out:
-       return rc;
+       return inode;
 }
 
 /**
@@ -219,26 +219,26 @@ out:
  *
  * Returns zero on success
  */
-static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
+static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
+                                   struct inode *ecryptfs_inode)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
-               &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+               &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        int rc = 0;
 
-       if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
+       if (S_ISDIR(ecryptfs_inode->i_mode)) {
                ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
                crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
                goto out;
        }
        ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
-       rc = ecryptfs_new_file_context(ecryptfs_dentry);
+       rc = ecryptfs_new_file_context(ecryptfs_inode);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error creating new file "
                                "context; rc = [%d]\n", rc);
                goto out;
        }
-       rc = ecryptfs_get_lower_file(ecryptfs_dentry,
-                                    ecryptfs_dentry->d_inode);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
                        "the lower file for the dentry with name "
@@ -246,10 +246,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                        ecryptfs_dentry->d_name.name, rc);
                goto out;
        }
-       rc = ecryptfs_write_metadata(ecryptfs_dentry);
+       rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode);
        if (rc)
                printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
-       ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
+       ecryptfs_put_lower_file(ecryptfs_inode);
 out:
        return rc;
 }
@@ -269,18 +269,28 @@ static int
 ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
                int mode, struct nameidata *nd)
 {
+       struct inode *ecryptfs_inode;
        int rc;
 
-       /* ecryptfs_do_create() calls ecryptfs_interpose() */
-       rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode);
-       if (unlikely(rc)) {
+       ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry,
+                                           mode);
+       if (unlikely(IS_ERR(ecryptfs_inode))) {
                ecryptfs_printk(KERN_WARNING, "Failed to create file in"
                                "lower filesystem\n");
+               rc = PTR_ERR(ecryptfs_inode);
                goto out;
        }
        /* At this point, a file exists on "disk"; we need to make sure
         * that this on disk file is prepared to be an ecryptfs file */
-       rc = ecryptfs_initialize_file(ecryptfs_dentry);
+       rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode);
+       if (rc) {
+               drop_nlink(ecryptfs_inode);
+               unlock_new_inode(ecryptfs_inode);
+               iput(ecryptfs_inode);
+               goto out;
+       }
+       d_instantiate(ecryptfs_dentry, ecryptfs_inode);
+       unlock_new_inode(ecryptfs_inode);
 out:
        return rc;
 }
index f6dba4505f1cc7e4f251f28a18bbeea5b3dcb2a7..12ccacda44e0288e13247e3e79ebd414287eb548 100644 (file)
@@ -565,7 +565,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
        brelse(bitmap_bh);
        printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu"
               ", computed = %llu, %llu\n",
-              EXT4_B2C(sbi, ext4_free_blocks_count(es)),
+              EXT4_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)),
               desc_count, bitmap_count);
        return bitmap_count;
 #else
index 240f6e2dc7eeb593e4143e05fc15e4565db155b1..848f436df29f6ffec6e8487549764d98c63d5b6b 100644 (file)
@@ -2270,6 +2270,7 @@ retry:
                        ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: "
                               "%ld pages, ino %lu; err %d", __func__,
                                wbc->nr_to_write, inode->i_ino, ret);
+                       blk_finish_plug(&plug);
                        goto out_writepages;
                }
 
@@ -2806,8 +2807,8 @@ out:
        spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 
        /* queue the work to convert unwritten extents to written */
-       queue_work(wq, &io_end->work);
        iocb->private = NULL;
+       queue_work(wq, &io_end->work);
 
        /* XXX: probably should move into the real I/O completion handler */
        inode_dio_done(inode);
index 9953d80145ad0f6331086053a7d80301c418f3a7..3858767ec672ef214ad5f288f30932ee0b5d933a 100644 (file)
@@ -1683,7 +1683,9 @@ static int parse_options(char *options, struct super_block *sb,
                        data_opt = EXT4_MOUNT_WRITEBACK_DATA;
                datacheck:
                        if (is_remount) {
-                               if (test_opt(sb, DATA_FLAGS) != data_opt) {
+                               if (!sbi->s_journal)
+                                       ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
+                               else if (test_opt(sb, DATA_FLAGS) != data_opt) {
                                        ext4_msg(sb, KERN_ERR,
                                                "Cannot change data mode on remount");
                                        return 0;
@@ -3099,8 +3101,6 @@ static void ext4_destroy_lazyinit_thread(void)
 }
 
 static int ext4_fill_super(struct super_block *sb, void *data, int silent)
-                               __releases(kernel_lock)
-                               __acquires(kernel_lock)
 {
        char *orig_data = kstrdup(data, GFP_KERNEL);
        struct buffer_head *bh;
index e673a88b8ae7560b14796b611aa57b267193411f..b1ce4c7ad3fb4f33e12ff4c8e320368b851e52c8 100644 (file)
@@ -40,6 +40,8 @@ int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in)
 
        src = in->name;
        srclen = in->len;
+       if (srclen > HFS_NAMELEN)
+               srclen = HFS_NAMELEN;
        dst = out;
        dstlen = HFS_MAX_NAMELEN;
        if (nls_io) {
index de4247021d25a0dae391d4c2e93f16f8b882d41e..5b6c9d1a2fb9bb3c99bf84d2ef0f6f67296491fa 100644 (file)
@@ -53,6 +53,78 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this,
        return 0;
 }
 
+/*
+ * jffs2_selected_compress:
+ * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
+ *     If 0, just take the first available compression mode.
+ * @data_in: Pointer to uncompressed data
+ * @cpage_out: Pointer to returned pointer to buffer for compressed data
+ * @datalen: On entry, holds the amount of data available for compression.
+ *     On exit, expected to hold the amount of data actually compressed.
+ * @cdatalen: On entry, holds the amount of space available for compressed
+ *     data. On exit, expected to hold the actual size of the compressed
+ *     data.
+ *
+ * Returns: the compression type used.  Zero is used to show that the data
+ * could not be compressed; probably because we couldn't find the requested
+ * compression mode.
+ */
+static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
+               unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
+{
+       struct jffs2_compressor *this;
+       int err, ret = JFFS2_COMPR_NONE;
+       uint32_t orig_slen, orig_dlen;
+       char *output_buf;
+
+       output_buf = kmalloc(*cdatalen, GFP_KERNEL);
+       if (!output_buf) {
+               printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
+               return ret;
+       }
+       orig_slen = *datalen;
+       orig_dlen = *cdatalen;
+       spin_lock(&jffs2_compressor_list_lock);
+       list_for_each_entry(this, &jffs2_compressor_list, list) {
+               /* Skip decompress-only and disabled modules */
+               if (!this->compress || this->disabled)
+                       continue;
+
+               /* Skip if not the desired compression type */
+               if (compr && (compr != this->compr))
+                       continue;
+
+               /*
+                * Either compression type was unspecified, or we found our
+                * compressor; either way, we're good to go.
+                */
+               this->usecount++;
+               spin_unlock(&jffs2_compressor_list_lock);
+
+               *datalen  = orig_slen;
+               *cdatalen = orig_dlen;
+               err = this->compress(data_in, output_buf, datalen, cdatalen);
+
+               spin_lock(&jffs2_compressor_list_lock);
+               this->usecount--;
+               if (!err) {
+                       /* Success */
+                       ret = this->compr;
+                       this->stat_compr_blocks++;
+                       this->stat_compr_orig_size += *datalen;
+                       this->stat_compr_new_size += *cdatalen;
+                       break;
+               }
+       }
+       spin_unlock(&jffs2_compressor_list_lock);
+       if (ret == JFFS2_COMPR_NONE)
+               kfree(output_buf);
+       else
+               *cpage_out = output_buf;
+
+       return ret;
+}
+
 /* jffs2_compress:
  * @data_in: Pointer to uncompressed data
  * @cpage_out: Pointer to returned pointer to buffer for compressed data
@@ -76,47 +148,23 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                        uint32_t *datalen, uint32_t *cdatalen)
 {
        int ret = JFFS2_COMPR_NONE;
-       int compr_ret;
+       int mode, compr_ret;
        struct jffs2_compressor *this, *best=NULL;
        unsigned char *output_buf = NULL, *tmp_buf;
        uint32_t orig_slen, orig_dlen;
        uint32_t best_slen=0, best_dlen=0;
 
-       switch (jffs2_compression_mode) {
+       if (c->mount_opts.override_compr)
+               mode = c->mount_opts.compr;
+       else
+               mode = jffs2_compression_mode;
+
+       switch (mode) {
        case JFFS2_COMPR_MODE_NONE:
                break;
        case JFFS2_COMPR_MODE_PRIORITY:
-               output_buf = kmalloc(*cdatalen,GFP_KERNEL);
-               if (!output_buf) {
-                       printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
-                       goto out;
-               }
-               orig_slen = *datalen;
-               orig_dlen = *cdatalen;
-               spin_lock(&jffs2_compressor_list_lock);
-               list_for_each_entry(this, &jffs2_compressor_list, list) {
-                       /* Skip decompress-only backwards-compatibility and disabled modules */
-                       if ((!this->compress)||(this->disabled))
-                               continue;
-
-                       this->usecount++;
-                       spin_unlock(&jffs2_compressor_list_lock);
-                       *datalen  = orig_slen;
-                       *cdatalen = orig_dlen;
-                       compr_ret = this->compress(data_in, output_buf, datalen, cdatalen);
-                       spin_lock(&jffs2_compressor_list_lock);
-                       this->usecount--;
-                       if (!compr_ret) {
-                               ret = this->compr;
-                               this->stat_compr_blocks++;
-                               this->stat_compr_orig_size += *datalen;
-                               this->stat_compr_new_size  += *cdatalen;
-                               break;
-                       }
-               }
-               spin_unlock(&jffs2_compressor_list_lock);
-               if (ret == JFFS2_COMPR_NONE)
-                       kfree(output_buf);
+               ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
+                               cdatalen);
                break;
        case JFFS2_COMPR_MODE_SIZE:
        case JFFS2_COMPR_MODE_FAVOURLZO:
@@ -174,22 +222,28 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                        best->stat_compr_orig_size += best_slen;
                        best->stat_compr_new_size  += best_dlen;
                        ret = best->compr;
+                       *cpage_out = output_buf;
                }
                spin_unlock(&jffs2_compressor_list_lock);
                break;
+       case JFFS2_COMPR_MODE_FORCELZO:
+               ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
+                               cpage_out, datalen, cdatalen);
+               break;
+       case JFFS2_COMPR_MODE_FORCEZLIB:
+               ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
+                               cpage_out, datalen, cdatalen);
+               break;
        default:
                printk(KERN_ERR "JFFS2: unknown compression mode.\n");
        }
- out:
+
        if (ret == JFFS2_COMPR_NONE) {
                *cpage_out = data_in;
                *datalen = *cdatalen;
                none_stat_compr_blocks++;
                none_stat_compr_size += *datalen;
        }
-       else {
-               *cpage_out = output_buf;
-       }
        return ret;
 }
 
index 13bb7597ab3987b5da405d5bd857e50b64dce4ab..5e91d578f4ed858c2ac575f375619000c5c6814c 100644 (file)
@@ -40,6 +40,8 @@
 #define JFFS2_COMPR_MODE_PRIORITY   1
 #define JFFS2_COMPR_MODE_SIZE       2
 #define JFFS2_COMPR_MODE_FAVOURLZO  3
+#define JFFS2_COMPR_MODE_FORCELZO   4
+#define JFFS2_COMPR_MODE_FORCEZLIB  5
 
 #define FAVOUR_LZO_PERCENT 80
 
index 7286e44ac66540822f65cd72bc4974435d8a9633..4b8afe39a87f2807859b9eda971b08ddc27dae7e 100644 (file)
@@ -379,7 +379,7 @@ void jffs2_dirty_inode(struct inode *inode, int flags)
        jffs2_do_setattr(inode, &iattr);
 }
 
-int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
+int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data)
 {
        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
 
index 0bc6a6c80a56d569054c14bed1865ea2979a0407..55a0c1dceadfddcf990b8fdbcfec015fc75fab32 100644 (file)
 
 struct jffs2_inodirty;
 
+struct jffs2_mount_opts {
+       bool override_compr;
+       unsigned int compr;
+};
+
 /* A struct for the overall file system control.  Pointers to
    jffs2_sb_info structs are named `c' in the source code.
    Nee jffs_control
@@ -126,6 +131,7 @@ struct jffs2_sb_info {
 #endif
 
        struct jffs2_summary *summary;          /* Summary information */
+       struct jffs2_mount_opts mount_opts;
 
 #ifdef CONFIG_JFFS2_FS_XATTR
 #define XATTRINDEX_HASHSIZE    (57)
index 6c1755c59c0ff9975a331d3217f751e274b221a0..ab65ee3ec858e9ad7a810a5174242c6e4222dcae 100644 (file)
@@ -176,7 +176,7 @@ void jffs2_dirty_inode(struct inode *inode, int flags);
 struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode,
                               struct jffs2_raw_inode *ri);
 int jffs2_statfs (struct dentry *, struct kstatfs *);
-int jffs2_remount_fs (struct super_block *, int *, char *);
+int jffs2_do_remount_fs(struct super_block *, int *, char *);
 int jffs2_do_fill_super(struct super_block *sb, void *data, int silent);
 void jffs2_gc_release_inode(struct jffs2_sb_info *c,
                            struct jffs2_inode_info *f);
index 8d8cd3419d02a75a7b0a7336da995a430324448b..28107ca136e481a556f686376292bf2244a78a91 100644 (file)
@@ -275,9 +275,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
        else
                c->mtd->unpoint(c->mtd, 0, c->mtd->size);
 #endif
-       if (s)
-               kfree(s);
-
+       kfree(s);
        return ret;
 }
 
index 853b8e300084cf2bb3c9941055ebc5aa433203e3..e7e97445411569d506ad5ac845e9cff3fc511971 100644 (file)
 #include <linux/fs.h>
 #include <linux/err.h>
 #include <linux/mount.h>
+#include <linux/parser.h>
 #include <linux/jffs2.h>
 #include <linux/pagemap.h>
 #include <linux/mtd/super.h>
 #include <linux/ctype.h>
 #include <linux/namei.h>
+#include <linux/seq_file.h>
 #include <linux/exportfs.h>
 #include "compr.h"
 #include "nodelist.h"
@@ -75,6 +77,37 @@ static void jffs2_write_super(struct super_block *sb)
        unlock_super(sb);
 }
 
+static const char *jffs2_compr_name(unsigned int compr)
+{
+       switch (compr) {
+       case JFFS2_COMPR_MODE_NONE:
+               return "none";
+#ifdef CONFIG_JFFS2_LZO
+       case JFFS2_COMPR_MODE_FORCELZO:
+               return "lzo";
+#endif
+#ifdef CONFIG_JFFS2_ZLIB
+       case JFFS2_COMPR_MODE_FORCEZLIB:
+               return "zlib";
+#endif
+       default:
+               /* should never happen; programmer error */
+               WARN_ON(1);
+               return "";
+       }
+}
+
+static int jffs2_show_options(struct seq_file *s, struct vfsmount *mnt)
+{
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(mnt->mnt_sb);
+       struct jffs2_mount_opts *opts = &c->mount_opts;
+
+       if (opts->override_compr)
+               seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr));
+
+       return 0;
+}
+
 static int jffs2_sync_fs(struct super_block *sb, int wait)
 {
        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
@@ -133,6 +166,85 @@ static const struct export_operations jffs2_export_ops = {
        .fh_to_parent = jffs2_fh_to_parent,
 };
 
+/*
+ * JFFS2 mount options.
+ *
+ * Opt_override_compr: override default compressor
+ * Opt_err: just end of array marker
+ */
+enum {
+       Opt_override_compr,
+       Opt_err,
+};
+
+static const match_table_t tokens = {
+       {Opt_override_compr, "compr=%s"},
+       {Opt_err, NULL},
+};
+
+static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
+{
+       substring_t args[MAX_OPT_ARGS];
+       char *p, *name;
+
+       if (!data)
+               return 0;
+
+       while ((p = strsep(&data, ","))) {
+               int token;
+
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_override_compr:
+                       name = match_strdup(&args[0]);
+
+                       if (!name)
+                               return -ENOMEM;
+                       if (!strcmp(name, "none"))
+                               c->mount_opts.compr = JFFS2_COMPR_MODE_NONE;
+#ifdef CONFIG_JFFS2_LZO
+                       else if (!strcmp(name, "lzo"))
+                               c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO;
+#endif
+#ifdef CONFIG_JFFS2_ZLIB
+                       else if (!strcmp(name, "zlib"))
+                               c->mount_opts.compr =
+                                               JFFS2_COMPR_MODE_FORCEZLIB;
+#endif
+                       else {
+                               printk(KERN_ERR "JFFS2 Error: unknown compressor \"%s\"",
+                                               name);
+                               kfree(name);
+                               return -EINVAL;
+                       }
+                       kfree(name);
+                       c->mount_opts.override_compr = true;
+                       break;
+               default:
+                       printk(KERN_ERR "JFFS2 Error: unrecognized mount option '%s' or missing value\n",
+                                       p);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+       int err;
+
+       err = jffs2_parse_options(c, data);
+       if (err)
+               return -EINVAL;
+
+       return jffs2_do_remount_fs(sb, flags, data);
+}
+
 static const struct super_operations jffs2_super_operations =
 {
        .alloc_inode =  jffs2_alloc_inode,
@@ -143,6 +255,7 @@ static const struct super_operations jffs2_super_operations =
        .remount_fs =   jffs2_remount_fs,
        .evict_inode =  jffs2_evict_inode,
        .dirty_inode =  jffs2_dirty_inode,
+       .show_options = jffs2_show_options,
        .sync_fs =      jffs2_sync_fs,
 };
 
@@ -166,6 +279,12 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
        c->os_priv = sb;
        sb->s_fs_info = c;
 
+       ret = jffs2_parse_options(c, data);
+       if (ret) {
+               kfree(c);
+               return -EINVAL;
+       }
+
        /* Initialize JFFS2 superblock locks, the further initialization will
         * be done later */
        mutex_init(&c->alloc_sem);
index 4515bea0268fa6ac17f8b2d61bd818bea42b6674..b09e51d2f81f98a1a985cdc410802b909bd361f2 100644 (file)
@@ -578,8 +578,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
        if (!jffs2_is_writebuffered(c))
                return 0;
 
-       if (mutex_trylock(&c->alloc_sem)) {
-               mutex_unlock(&c->alloc_sem);
+       if (!mutex_is_locked(&c->alloc_sem)) {
                printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
                BUG();
        }
@@ -1026,7 +1025,7 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
        int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
        struct mtd_oob_ops ops;
 
-       ops.mode = MTD_OOB_AUTO;
+       ops.mode = MTD_OPS_AUTO_OOB;
        ops.ooblen = NR_OOB_SCAN_PAGES * c->oobavail;
        ops.oobbuf = c->oobbuf;
        ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
@@ -1069,7 +1068,7 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
        struct mtd_oob_ops ops;
        int ret, cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 
-       ops.mode = MTD_OOB_AUTO;
+       ops.mode = MTD_OPS_AUTO_OOB;
        ops.ooblen = cmlen;
        ops.oobbuf = c->oobbuf;
        ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
@@ -1095,7 +1094,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
        struct mtd_oob_ops ops;
        int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 
-       ops.mode = MTD_OOB_AUTO;
+       ops.mode = MTD_OPS_AUTO_OOB;
        ops.ooblen = cmlen;
        ops.oobbuf = (uint8_t *)&oob_cleanmarker;
        ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
index 3f32bcb0d9bd5beb882b67480ff3593d202f5837..ef175cb8cfd8e20be4be8496660521a371297a50 100644 (file)
 #include <linux/bitops.h>
 #include <linux/sched.h>
 
-static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
-
 static DEFINE_SPINLOCK(bitmap_lock);
 
-static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits)
+/*
+ * bitmap consists of blocks filled with 16bit words
+ * bit set == busy, bit clear == free
+ * endianness is a mess, but for counting zero bits it really doesn't matter...
+ */
+static __u32 count_free(struct buffer_head *map[], unsigned blocksize, __u32 numbits)
 {
-       unsigned i, j, sum = 0;
-       struct buffer_head *bh;
-  
-       for (i=0; i<numblocks-1; i++) {
-               if (!(bh=map[i])) 
-                       return(0);
-               for (j=0; j<bh->b_size; j++)
-                       sum += nibblemap[bh->b_data[j] & 0xf]
-                               + nibblemap[(bh->b_data[j]>>4) & 0xf];
-       }
+       __u32 sum = 0;
+       unsigned blocks = DIV_ROUND_UP(numbits, blocksize * 8);
 
-       if (numblocks==0 || !(bh=map[numblocks-1]))
-               return(0);
-       i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
-       for (j=0; j<i; j++) {
-               sum += nibblemap[bh->b_data[j] & 0xf]
-                       + nibblemap[(bh->b_data[j]>>4) & 0xf];
+       while (blocks--) {
+               unsigned words = blocksize / 2;
+               __u16 *p = (__u16 *)(*map++)->b_data;
+               while (words--)
+                       sum += 16 - hweight16(*p++);
        }
 
-       i = numbits%16;
-       if (i!=0) {
-               i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1);
-               sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf];
-               sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf];
-       }
-       return(sum);
+       return sum;
 }
 
 void minix_free_block(struct inode *inode, unsigned long block)
@@ -105,10 +93,12 @@ int minix_new_block(struct inode * inode)
        return 0;
 }
 
-unsigned long minix_count_free_blocks(struct minix_sb_info *sbi)
+unsigned long minix_count_free_blocks(struct super_block *sb)
 {
-       return (count_free(sbi->s_zmap, sbi->s_zmap_blocks,
-               sbi->s_nzones - sbi->s_firstdatazone + 1)
+       struct minix_sb_info *sbi = minix_sb(sb);
+       u32 bits = sbi->s_nzones - (sbi->s_firstdatazone + 1);
+
+       return (count_free(sbi->s_zmap, sb->s_blocksize, bits)
                << sbi->s_log_zone_size);
 }
 
@@ -273,7 +263,10 @@ struct inode *minix_new_inode(const struct inode *dir, int mode, int *error)
        return inode;
 }
 
-unsigned long minix_count_free_inodes(struct minix_sb_info *sbi)
+unsigned long minix_count_free_inodes(struct super_block *sb)
 {
-       return count_free(sbi->s_imap, sbi->s_imap_blocks, sbi->s_ninodes + 1);
+       struct minix_sb_info *sbi = minix_sb(sb);
+       u32 bits = sbi->s_ninodes + 1;
+
+       return count_free(sbi->s_imap, sb->s_blocksize, bits);
 }
index 64cdcd662ffccca98fecad85103f10a2348a76bc..1d9e33966db089eb2ba5ed3f7aab9967bd2c0b4e 100644 (file)
@@ -279,6 +279,27 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        else if (sbi->s_mount_state & MINIX_ERROR_FS)
                printk("MINIX-fs: mounting file system with errors, "
                        "running fsck is recommended\n");
+
+       /* Apparently minix can create filesystems that allocate more blocks for
+        * the bitmaps than needed.  We simply ignore that, but verify it didn't
+        * create one with not enough blocks and bail out if so.
+        */
+       block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize);
+       if (sbi->s_imap_blocks < block) {
+               printk("MINIX-fs: file system does not have enough "
+                               "imap blocks allocated.  Refusing to mount\n");
+               goto out_iput;
+       }
+
+       block = minix_blocks_needed(
+                       (sbi->s_nzones - (sbi->s_firstdatazone + 1)),
+                       s->s_blocksize);
+       if (sbi->s_zmap_blocks < block) {
+               printk("MINIX-fs: file system does not have enough "
+                               "zmap blocks allocated.  Refusing to mount.\n");
+               goto out_iput;
+       }
+
        return 0;
 
 out_iput:
@@ -339,10 +360,10 @@ static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_type = sb->s_magic;
        buf->f_bsize = sb->s_blocksize;
        buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
-       buf->f_bfree = minix_count_free_blocks(sbi);
+       buf->f_bfree = minix_count_free_blocks(sb);
        buf->f_bavail = buf->f_bfree;
        buf->f_files = sbi->s_ninodes;
-       buf->f_ffree = minix_count_free_inodes(sbi);
+       buf->f_ffree = minix_count_free_inodes(sb);
        buf->f_namelen = sbi->s_namelen;
        buf->f_fsid.val[0] = (u32)id;
        buf->f_fsid.val[1] = (u32)(id >> 32);
index 341e2122879a7604611426d4f702f211ee3ed59a..26bbd55e82ea2ab42f61fa2898fd45fee17f7074 100644 (file)
@@ -48,10 +48,10 @@ extern struct minix_inode * minix_V1_raw_inode(struct super_block *, ino_t, stru
 extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **);
 extern struct inode * minix_new_inode(const struct inode *, int, int *);
 extern void minix_free_inode(struct inode * inode);
-extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi);
+extern unsigned long minix_count_free_inodes(struct super_block *sb);
 extern int minix_new_block(struct inode * inode);
 extern void minix_free_block(struct inode *inode, unsigned long block);
-extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
+extern unsigned long minix_count_free_blocks(struct super_block *sb);
 extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len);
 
@@ -88,6 +88,11 @@ static inline struct minix_inode_info *minix_i(struct inode *inode)
        return list_entry(inode, struct minix_inode_info, vfs_inode);
 }
 
+static inline unsigned minix_blocks_needed(unsigned bits, unsigned blocksize)
+{
+       return DIV_ROUND_UP(bits, blocksize * 8);
+}
+
 #if defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) && \
        defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED)
 
@@ -125,7 +130,7 @@ static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)
        if (!size)
                return 0;
 
-       size = (size >> 4) + ((size & 15) > 0);
+       size >>= 4;
        while (*p++ == 0xffff) {
                if (--size == 0)
                        return (p - addr) << 4;
index ac6d214da82790a8f16671e59dfffaf49e4c75bd..5008f01787f5681730a9273693a1a863e7e6cc7e 100644 (file)
@@ -852,7 +852,7 @@ static int follow_managed(struct path *path, unsigned flags)
                mntput(path->mnt);
        if (ret == -EISDIR)
                ret = 0;
-       return ret;
+       return ret < 0 ? ret : need_mntput;
 }
 
 int follow_down_one(struct path *path)
@@ -900,6 +900,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                        break;
                path->mnt = mounted;
                path->dentry = mounted->mnt_root;
+               nd->flags |= LOOKUP_JUMPED;
                nd->seq = read_seqcount_begin(&path->dentry->d_seq);
                /*
                 * Update the inode too. We don't need to re-check the
@@ -1213,6 +1214,8 @@ retry:
                path_put_conditional(path, nd);
                return err;
        }
+       if (err)
+               nd->flags |= LOOKUP_JUMPED;
        *inode = path->dentry->d_inode;
        return 0;
 }
@@ -2146,6 +2149,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
        }
 
        /* create side of things */
+       /*
+        * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED has been
+        * cleared when we got to the last component we are about to look up
+        */
        error = complete_walk(nd);
        if (error)
                return ERR_PTR(error);
@@ -2214,6 +2221,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
        if (error < 0)
                goto exit_dput;
 
+       if (error)
+               nd->flags |= LOOKUP_JUMPED;
+
        error = -ENOENT;
        if (!path->dentry->d_inode)
                goto exit_dput;
@@ -2223,6 +2233,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
 
        path_to_nameidata(path, nd);
        nd->inode = path->dentry->d_inode;
+       /* Why this, you ask?  _Now_ we might have grown LOOKUP_JUMPED... */
+       error = complete_walk(nd);
+       if (error)
+               goto exit;
        error = -EISDIR;
        if (S_ISDIR(nd->inode->i_mode))
                goto exit;
index e5e1c7d1839b791f0c52428a9ffe058bd7ded092..6d3a1963879b0f13fd4929195a19c958d9deb4bb 100644 (file)
@@ -2483,11 +2483,43 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
                __mnt_make_longterm(mnt);
                new_ns->root = mnt;
                list_add(&new_ns->list, &new_ns->root->mnt_list);
+       } else {
+               mntput(mnt);
        }
        return new_ns;
 }
 EXPORT_SYMBOL(create_mnt_ns);
 
+struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
+{
+       struct mnt_namespace *ns;
+       struct super_block *s;
+       struct path path;
+       int err;
+
+       ns = create_mnt_ns(mnt);
+       if (IS_ERR(ns))
+               return ERR_CAST(ns);
+
+       err = vfs_path_lookup(mnt->mnt_root, mnt,
+                       name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
+
+       put_mnt_ns(ns);
+
+       if (err)
+               return ERR_PTR(err);
+
+       /* trade a vfsmount reference for active sb one */
+       s = path.mnt->mnt_sb;
+       atomic_inc(&s->s_active);
+       mntput(path.mnt);
+       /* lock the sucker */
+       down_write(&s->s_umount);
+       /* ... and return the root of (sub)tree on it */
+       return path.dentry;
+}
+EXPORT_SYMBOL(mount_subtree);
+
 SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
                char __user *, type, unsigned long, flags, void __user *, data)
 {
index b238d95ac48c7b926ff1e02eae157ea09fa58a68..ac289909814768a626ad817dbf40627805e7899e 100644 (file)
@@ -1468,12 +1468,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:
                                res = ERR_CAST(inode);
index 0a1f8312b4dcf0fe9272310f1ab6d00178cdd2a8..eca56d4b39c0ae82caf3abb117bb9ad5163ec1b3 100644 (file)
 
 #define NFSDBG_FACILITY                NFSDBG_FILE
 
-static int nfs_file_open(struct inode *, struct file *);
-static int nfs_file_release(struct inode *, struct file *);
-static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
-static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
-static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos,
-                                       struct pipe_inode_info *pipe,
-                                       size_t count, unsigned int flags);
-static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t pos);
-static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
-                                       struct file *filp, loff_t *ppos,
-                                       size_t count, unsigned int flags);
-static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t pos);
-static int  nfs_file_flush(struct file *, fl_owner_t id);
-static int  nfs_file_fsync(struct file *, loff_t, loff_t, int datasync);
-static int nfs_check_flags(int flags);
-static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
-static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
-static int nfs_setlease(struct file *file, long arg, struct file_lock **fl);
-
 static const struct vm_operations_struct nfs_file_vm_ops;
 
-const struct file_operations nfs_file_operations = {
-       .llseek         = nfs_file_llseek,
-       .read           = do_sync_read,
-       .write          = do_sync_write,
-       .aio_read       = nfs_file_read,
-       .aio_write      = nfs_file_write,
-       .mmap           = nfs_file_mmap,
-       .open           = nfs_file_open,
-       .flush          = nfs_file_flush,
-       .release        = nfs_file_release,
-       .fsync          = nfs_file_fsync,
-       .lock           = nfs_lock,
-       .flock          = nfs_flock,
-       .splice_read    = nfs_file_splice_read,
-       .splice_write   = nfs_file_splice_write,
-       .check_flags    = nfs_check_flags,
-       .setlease       = nfs_setlease,
-};
-
 const struct inode_operations nfs_file_inode_operations = {
        .permission     = nfs_permission,
        .getattr        = nfs_getattr,
@@ -886,3 +846,54 @@ static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
                        file->f_path.dentry->d_name.name, arg);
        return -EINVAL;
 }
+
+const struct file_operations nfs_file_operations = {
+       .llseek         = nfs_file_llseek,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
+       .aio_read       = nfs_file_read,
+       .aio_write      = nfs_file_write,
+       .mmap           = nfs_file_mmap,
+       .open           = nfs_file_open,
+       .flush          = nfs_file_flush,
+       .release        = nfs_file_release,
+       .fsync          = nfs_file_fsync,
+       .lock           = nfs_lock,
+       .flock          = nfs_flock,
+       .splice_read    = nfs_file_splice_read,
+       .splice_write   = nfs_file_splice_write,
+       .check_flags    = nfs_check_flags,
+       .setlease       = nfs_setlease,
+};
+
+#ifdef CONFIG_NFS_V4
+static int
+nfs4_file_open(struct inode *inode, struct file *filp)
+{
+       /*
+        * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to
+        * this point, then something is very wrong
+        */
+       dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp);
+       return -ENOTDIR;
+}
+
+const struct file_operations nfs4_file_operations = {
+       .llseek         = nfs_file_llseek,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
+       .aio_read       = nfs_file_read,
+       .aio_write      = nfs_file_write,
+       .mmap           = nfs_file_mmap,
+       .open           = nfs4_file_open,
+       .flush          = nfs_file_flush,
+       .release        = nfs_file_release,
+       .fsync          = nfs_file_fsync,
+       .lock           = nfs_lock,
+       .flock          = nfs_flock,
+       .splice_read    = nfs_file_splice_read,
+       .splice_write   = nfs_file_splice_write,
+       .check_flags    = nfs_check_flags,
+       .setlease       = nfs_setlease,
+};
+#endif /* CONFIG_NFS_V4 */
index c07a55aec83867ee1489ff29134862bc891dfa82..50a15fa8cf985e41e21b786f4f6d9d9ed96cf37e 100644 (file)
@@ -291,7 +291,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                 */
                inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops;
                if (S_ISREG(inode->i_mode)) {
-                       inode->i_fop = &nfs_file_operations;
+                       inode->i_fop = NFS_SB(sb)->nfs_client->rpc_ops->file_ops;
                        inode->i_data.a_ops = &nfs_file_aops;
                        inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info;
                } else if (S_ISDIR(inode->i_mode)) {
index c1a1bd8ddf1cbecfbba4f375fec6c78d5d36ae60..3f4d95751d52f3e152fc7f2dcb5d1a6d8fc2184b 100644 (file)
@@ -299,6 +299,8 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
 extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
                struct list_head *head);
 
+extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
+               struct inode *inode);
 extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
 extern void nfs_readdata_release(struct nfs_read_data *rdata);
 
index 85f1690ca08c110bcd1c1754e564f23619295a1a..d4bc9ed917484106dbed777942e0db096be08236 100644 (file)
@@ -853,6 +853,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .dentry_ops     = &nfs_dentry_operations,
        .dir_inode_ops  = &nfs3_dir_inode_operations,
        .file_inode_ops = &nfs3_file_inode_operations,
+       .file_ops       = &nfs_file_operations,
        .getroot        = nfs3_proc_get_root,
        .getattr        = nfs3_proc_getattr,
        .setattr        = nfs3_proc_setattr,
index b60fddf606f7d23e6f01305420446d74102001a7..be2bbac13817c7ec624363afb4caf8bdd65a72b4 100644 (file)
@@ -2464,8 +2464,7 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst
                case -NFS4ERR_BADNAME:
                        return -ENOENT;
                case -NFS4ERR_MOVED:
-                       err = nfs4_get_referral(dir, name, fattr, fhandle);
-                       break;
+                       return nfs4_get_referral(dir, name, fattr, fhandle);
                case -NFS4ERR_WRONGSEC:
                        nfs_fixup_secinfo_attributes(fattr, fhandle);
                }
@@ -6253,6 +6252,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .dentry_ops     = &nfs4_dentry_operations,
        .dir_inode_ops  = &nfs4_dir_inode_operations,
        .file_inode_ops = &nfs4_file_inode_operations,
+       .file_ops       = &nfs4_file_operations,
        .getroot        = nfs4_proc_get_root,
        .getattr        = nfs4_proc_getattr,
        .setattr        = nfs4_proc_setattr,
index baf73536bc048e2085fabde5c2f523a6fbc3b523..8e672a2b2d693193e8ca7252d70c73578d739e0f 100644 (file)
@@ -1260,6 +1260,25 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
 
+static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
+{
+       struct nfs_pageio_descriptor pgio;
+
+       put_lseg(data->lseg);
+       data->lseg = NULL;
+       dprintk("pnfs write error = %d\n", data->pnfs_error);
+
+       nfs_pageio_init_read_mds(&pgio, data->inode);
+
+       while (!list_empty(&data->pages)) {
+               struct nfs_page *req = nfs_list_entry(data->pages.next);
+
+               nfs_list_remove_request(req);
+               nfs_pageio_add_request(&pgio, req);
+       }
+       nfs_pageio_complete(&pgio);
+}
+
 /*
  * Called by non rpc-based layout drivers
  */
@@ -1268,11 +1287,8 @@ void pnfs_ld_read_done(struct nfs_read_data *data)
        if (likely(!data->pnfs_error)) {
                __nfs4_read_done_cb(data);
                data->mds_ops->rpc_call_done(&data->task, data);
-       } else {
-               put_lseg(data->lseg);
-               data->lseg = NULL;
-               dprintk("pnfs write error = %d\n", data->pnfs_error);
-       }
+       } else
+               pnfs_ld_handle_read_error(data);
        data->mds_ops->rpc_release(data);
 }
 EXPORT_SYMBOL_GPL(pnfs_ld_read_done);
index ac40b8535d7e0e7493f13063afdbe57169837c9e..f48125da198a2d5a50bc0861805212a129427920 100644 (file)
@@ -710,6 +710,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
        .dentry_ops     = &nfs_dentry_operations,
        .dir_inode_ops  = &nfs_dir_inode_operations,
        .file_inode_ops = &nfs_file_inode_operations,
+       .file_ops       = &nfs_file_operations,
        .getroot        = nfs_proc_get_root,
        .getattr        = nfs_proc_getattr,
        .setattr        = nfs_proc_setattr,
index 8b48ec63f7229de8cb9435cfe82cc9d9876e6268..cfa175c223dcfa5b79ebf17b3d609649fbd7188d 100644 (file)
@@ -109,7 +109,7 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
        }
 }
 
-static void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
+void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
                struct inode *inode)
 {
        nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops,
@@ -534,23 +534,13 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
 static void nfs_readpage_release_full(void *calldata)
 {
        struct nfs_read_data *data = calldata;
-       struct nfs_pageio_descriptor pgio;
 
-       if (data->pnfs_error) {
-               nfs_pageio_init_read_mds(&pgio, data->inode);
-               pgio.pg_recoalesce = 1;
-       }
        while (!list_empty(&data->pages)) {
                struct nfs_page *req = nfs_list_entry(data->pages.next);
 
                nfs_list_remove_request(req);
-               if (!data->pnfs_error)
-                       nfs_readpage_release(req);
-               else
-                       nfs_pageio_add_request(&pgio, req);
+               nfs_readpage_release(req);
        }
-       if (data->pnfs_error)
-               nfs_pageio_complete(&pgio);
        nfs_readdata_release(calldata);
 }
 
index 480b3b6bf71ef82f122a433cbf3ec62d789c033a..134777406ee31938271db7ad0af8c8cb444e6fc9 100644 (file)
@@ -2787,43 +2787,18 @@ static void nfs_referral_loop_unprotect(void)
 static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
                const char *export_path)
 {
-       struct mnt_namespace *ns_private;
-       struct super_block *s;
        struct dentry *dentry;
-       struct path path;
-       int ret;
-
-       ns_private = create_mnt_ns(root_mnt);
-       ret = PTR_ERR(ns_private);
-       if (IS_ERR(ns_private))
-               goto out_mntput;
-
-       ret = nfs_referral_loop_protect();
-       if (ret != 0)
-               goto out_put_mnt_ns;
+       int ret = nfs_referral_loop_protect();
 
-       ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt,
-                       export_path, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
+       if (ret) {
+               mntput(root_mnt);
+               return ERR_PTR(ret);
+       }
 
+       dentry = mount_subtree(root_mnt, export_path);
        nfs_referral_loop_unprotect();
-       put_mnt_ns(ns_private);
-
-       if (ret != 0)
-               goto out_err;
-
-       s = path.mnt->mnt_sb;
-       atomic_inc(&s->s_active);
-       dentry = dget(path.dentry);
 
-       path_put(&path);
-       down_write(&s->s_umount);
        return dentry;
-out_put_mnt_ns:
-       put_mnt_ns(ns_private);
-out_mntput:
-       mntput(root_mnt);
-out_err:
-       return ERR_PTR(ret);
 }
 
 static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
index ed553c60de827e0ebad24e3501e0e00d21c82cfc..3165aebb43c87934b743ecf08e5f02cef586d771 100644 (file)
@@ -5699,7 +5699,7 @@ int ocfs2_remove_btree_range(struct inode *inode,
                                           OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto out;
+               goto out_commit;
        }
 
        dquot_free_space_nodirty(inode,
index c1efe939c774e2c9b909892f6c95434d6da760ee..78b68af3b0e32627b1874277d8ae58003501acb5 100644 (file)
@@ -290,7 +290,15 @@ static int ocfs2_readpage(struct file *file, struct page *page)
        }
 
        if (down_read_trylock(&oi->ip_alloc_sem) == 0) {
+               /*
+                * Unlock the page and cycle ip_alloc_sem so that we don't
+                * busyloop waiting for ip_alloc_sem to unlock
+                */
                ret = AOP_TRUNCATED_PAGE;
+               unlock_page(page);
+               unlock = 0;
+               down_read(&oi->ip_alloc_sem);
+               up_read(&oi->ip_alloc_sem);
                goto out_inode_unlock;
        }
 
@@ -563,6 +571,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
 {
        struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
        int level;
+       wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
 
        /* this io's submitter should not have unlocked this before we could */
        BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
@@ -570,6 +579,15 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
        if (ocfs2_iocb_is_sem_locked(iocb))
                ocfs2_iocb_clear_sem_locked(iocb);
 
+       if (ocfs2_iocb_is_unaligned_aio(iocb)) {
+               ocfs2_iocb_clear_unaligned_aio(iocb);
+
+               if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) &&
+                   waitqueue_active(wq)) {
+                       wake_up_all(wq);
+               }
+       }
+
        ocfs2_iocb_clear_rw_locked(iocb);
 
        level = ocfs2_iocb_rw_locked_level(iocb);
@@ -862,6 +880,12 @@ struct ocfs2_write_ctxt {
        struct page                     *w_pages[OCFS2_MAX_CTXT_PAGES];
        struct page                     *w_target_page;
 
+       /*
+        * w_target_locked is used for page_mkwrite path indicating no unlocking
+        * against w_target_page in ocfs2_write_end_nolock.
+        */
+       unsigned int                    w_target_locked:1;
+
        /*
         * ocfs2_write_end() uses this to know what the real range to
         * write in the target should be.
@@ -895,6 +919,24 @@ void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages)
 
 static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
 {
+       int i;
+
+       /*
+        * w_target_locked is only set to true in the page_mkwrite() case.
+        * The intent is to allow us to lock the target page from write_begin()
+        * to write_end(). The caller must hold a ref on w_target_page.
+        */
+       if (wc->w_target_locked) {
+               BUG_ON(!wc->w_target_page);
+               for (i = 0; i < wc->w_num_pages; i++) {
+                       if (wc->w_target_page == wc->w_pages[i]) {
+                               wc->w_pages[i] = NULL;
+                               break;
+                       }
+               }
+               mark_page_accessed(wc->w_target_page);
+               page_cache_release(wc->w_target_page);
+       }
        ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages);
 
        brelse(wc->w_di_bh);
@@ -1132,20 +1174,17 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
                         */
                        lock_page(mmap_page);
 
+                       /* Exit and let the caller retry */
                        if (mmap_page->mapping != mapping) {
+                               WARN_ON(mmap_page->mapping);
                                unlock_page(mmap_page);
-                               /*
-                                * Sanity check - the locking in
-                                * ocfs2_pagemkwrite() should ensure
-                                * that this code doesn't trigger.
-                                */
-                               ret = -EINVAL;
-                               mlog_errno(ret);
+                               ret = -EAGAIN;
                                goto out;
                        }
 
                        page_cache_get(mmap_page);
                        wc->w_pages[i] = mmap_page;
+                       wc->w_target_locked = true;
                } else {
                        wc->w_pages[i] = find_or_create_page(mapping, index,
                                                             GFP_NOFS);
@@ -1160,6 +1199,8 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
                        wc->w_target_page = wc->w_pages[i];
        }
 out:
+       if (ret)
+               wc->w_target_locked = false;
        return ret;
 }
 
@@ -1817,11 +1858,23 @@ try_again:
         */
        ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, len,
                                         cluster_of_pages, mmap_page);
-       if (ret) {
+       if (ret && ret != -EAGAIN) {
                mlog_errno(ret);
                goto out_quota;
        }
 
+       /*
+        * ocfs2_grab_pages_for_write() returns -EAGAIN if it could not lock
+        * the target page. In this case, we exit with no error and no target
+        * page. This will trigger the caller, page_mkwrite(), to re-try
+        * the operation.
+        */
+       if (ret == -EAGAIN) {
+               BUG_ON(wc->w_target_page);
+               ret = 0;
+               goto out_quota;
+       }
+
        ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
                                          len);
        if (ret) {
index 75cf3ad987a66d911c15234a803243185ccc5a94..ffb2da370a99d05dd4b919fc64a5483dbc2df7a3 100644 (file)
@@ -78,6 +78,7 @@ enum ocfs2_iocb_lock_bits {
        OCFS2_IOCB_RW_LOCK = 0,
        OCFS2_IOCB_RW_LOCK_LEVEL,
        OCFS2_IOCB_SEM,
+       OCFS2_IOCB_UNALIGNED_IO,
        OCFS2_IOCB_NUM_LOCKS
 };
 
@@ -91,4 +92,17 @@ enum ocfs2_iocb_lock_bits {
        clear_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
 #define ocfs2_iocb_is_sem_locked(iocb) \
        test_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
+
+#define ocfs2_iocb_set_unaligned_aio(iocb) \
+       set_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_clear_unaligned_aio(iocb) \
+       clear_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_is_unaligned_aio(iocb) \
+       test_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
+
+#define OCFS2_IOEND_WQ_HASH_SZ 37
+#define ocfs2_ioend_wq(v)   (&ocfs2__ioend_wq[((unsigned long)(v)) %\
+                                           OCFS2_IOEND_WQ_HASH_SZ])
+extern wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ];
+
 #endif /* OCFS2_FILE_H */
index 9a3e6bbff27bd4839b487c2c14282fd9ef1a4675..a4e855e3690e6ab844d37788b71649975321cb19 100644 (file)
@@ -216,6 +216,7 @@ struct o2hb_region {
 
        struct list_head        hr_all_item;
        unsigned                hr_unclean_stop:1,
+                               hr_aborted_start:1,
                                hr_item_pinned:1,
                                hr_item_dropped:1;
 
@@ -254,6 +255,10 @@ struct o2hb_region {
         * a more complete api that doesn't lead to this sort of fragility. */
        atomic_t                hr_steady_iterations;
 
+       /* terminate o2hb thread if it does not reach steady state
+        * (hr_steady_iterations == 0) within hr_unsteady_iterations */
+       atomic_t                hr_unsteady_iterations;
+
        char                    hr_dev_name[BDEVNAME_SIZE];
 
        unsigned int            hr_timeout_ms;
@@ -324,6 +329,10 @@ static void o2hb_write_timeout(struct work_struct *work)
 
 static void o2hb_arm_write_timeout(struct o2hb_region *reg)
 {
+       /* Arm writeout only after thread reaches steady state */
+       if (atomic_read(&reg->hr_steady_iterations) != 0)
+               return;
+
        mlog(ML_HEARTBEAT, "Queue write timeout for %u ms\n",
             O2HB_MAX_WRITE_TIMEOUT_MS);
 
@@ -537,9 +546,14 @@ static int o2hb_verify_crc(struct o2hb_region *reg,
        return read == computed;
 }
 
-/* We want to make sure that nobody is heartbeating on top of us --
- * this will help detect an invalid configuration. */
-static void o2hb_check_last_timestamp(struct o2hb_region *reg)
+/*
+ * Compare the slot data with what we wrote in the last iteration.
+ * If the match fails, print an appropriate error message. This is to
+ * detect errors like... another node hearting on the same slot,
+ * flaky device that is losing writes, etc.
+ * Returns 1 if check succeeds, 0 otherwise.
+ */
+static int o2hb_check_own_slot(struct o2hb_region *reg)
 {
        struct o2hb_disk_slot *slot;
        struct o2hb_disk_heartbeat_block *hb_block;
@@ -548,13 +562,13 @@ static void o2hb_check_last_timestamp(struct o2hb_region *reg)
        slot = &reg->hr_slots[o2nm_this_node()];
        /* Don't check on our 1st timestamp */
        if (!slot->ds_last_time)
-               return;
+               return 0;
 
        hb_block = slot->ds_raw_block;
        if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time &&
            le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation &&
            hb_block->hb_node == slot->ds_node_num)
-               return;
+               return 1;
 
 #define ERRSTR1                "Another node is heartbeating on device"
 #define ERRSTR2                "Heartbeat generation mismatch on device"
@@ -574,6 +588,8 @@ static void o2hb_check_last_timestamp(struct o2hb_region *reg)
             (unsigned long long)slot->ds_last_time, hb_block->hb_node,
             (unsigned long long)le64_to_cpu(hb_block->hb_generation),
             (unsigned long long)le64_to_cpu(hb_block->hb_seq));
+
+       return 0;
 }
 
 static inline void o2hb_prepare_block(struct o2hb_region *reg,
@@ -719,17 +735,24 @@ static void o2hb_shutdown_slot(struct o2hb_disk_slot *slot)
        o2nm_node_put(node);
 }
 
-static void o2hb_set_quorum_device(struct o2hb_region *reg,
-                                  struct o2hb_disk_slot *slot)
+static void o2hb_set_quorum_device(struct o2hb_region *reg)
 {
-       assert_spin_locked(&o2hb_live_lock);
-
        if (!o2hb_global_heartbeat_active())
                return;
 
-       if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+       /* Prevent race with o2hb_heartbeat_group_drop_item() */
+       if (kthread_should_stop())
+               return;
+
+       /* Tag region as quorum only after thread reaches steady state */
+       if (atomic_read(&reg->hr_steady_iterations) != 0)
                return;
 
+       spin_lock(&o2hb_live_lock);
+
+       if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+               goto unlock;
+
        /*
         * A region can be added to the quorum only when it sees all
         * live nodes heartbeat on it. In other words, the region has been
@@ -737,13 +760,10 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg,
         */
        if (memcmp(reg->hr_live_node_bitmap, o2hb_live_node_bitmap,
                   sizeof(o2hb_live_node_bitmap)))
-               return;
-
-       if (slot->ds_changed_samples < O2HB_LIVE_THRESHOLD)
-               return;
+               goto unlock;
 
-       printk(KERN_NOTICE "o2hb: Region %s is now a quorum device\n",
-              config_item_name(&reg->hr_item));
+       printk(KERN_NOTICE "o2hb: Region %s (%s) is now a quorum device\n",
+              config_item_name(&reg->hr_item), reg->hr_dev_name);
 
        set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap);
 
@@ -754,6 +774,8 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg,
        if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
                           O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF)
                o2hb_region_unpin(NULL);
+unlock:
+       spin_unlock(&o2hb_live_lock);
 }
 
 static int o2hb_check_slot(struct o2hb_region *reg,
@@ -925,8 +947,6 @@ fire_callbacks:
                slot->ds_equal_samples = 0;
        }
 out:
-       o2hb_set_quorum_device(reg, slot);
-
        spin_unlock(&o2hb_live_lock);
 
        o2hb_run_event_list(&event);
@@ -957,7 +977,8 @@ static int o2hb_highest_node(unsigned long *nodes,
 
 static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
 {
-       int i, ret, highest_node, change = 0;
+       int i, ret, highest_node;
+       int membership_change = 0, own_slot_ok = 0;
        unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
        unsigned long live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
        struct o2hb_bio_wait_ctxt write_wc;
@@ -966,7 +987,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
                                       sizeof(configured_nodes));
        if (ret) {
                mlog_errno(ret);
-               return ret;
+               goto bail;
        }
 
        /*
@@ -982,8 +1003,9 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
 
        highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
        if (highest_node >= O2NM_MAX_NODES) {
-               mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n");
-               return -EINVAL;
+               mlog(ML_NOTICE, "o2hb: No configured nodes found!\n");
+               ret = -EINVAL;
+               goto bail;
        }
 
        /* No sense in reading the slots of nodes that don't exist
@@ -993,29 +1015,27 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
        ret = o2hb_read_slots(reg, highest_node + 1);
        if (ret < 0) {
                mlog_errno(ret);
-               return ret;
+               goto bail;
        }
 
        /* With an up to date view of the slots, we can check that no
         * other node has been improperly configured to heartbeat in
         * our slot. */
-       o2hb_check_last_timestamp(reg);
+       own_slot_ok = o2hb_check_own_slot(reg);
 
        /* fill in the proper info for our next heartbeat */
        o2hb_prepare_block(reg, reg->hr_generation);
 
-       /* And fire off the write. Note that we don't wait on this I/O
-        * until later. */
        ret = o2hb_issue_node_write(reg, &write_wc);
        if (ret < 0) {
                mlog_errno(ret);
-               return ret;
+               goto bail;
        }
 
        i = -1;
        while((i = find_next_bit(configured_nodes,
                                 O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
-               change |= o2hb_check_slot(reg, &reg->hr_slots[i]);
+               membership_change |= o2hb_check_slot(reg, &reg->hr_slots[i]);
        }
 
        /*
@@ -1030,18 +1050,39 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
                 * disk */
                mlog(ML_ERROR, "Write error %d on device \"%s\"\n",
                     write_wc.wc_error, reg->hr_dev_name);
-               return write_wc.wc_error;
+               ret = write_wc.wc_error;
+               goto bail;
        }
 
-       o2hb_arm_write_timeout(reg);
+       /* Skip disarming the timeout if own slot has stale/bad data */
+       if (own_slot_ok) {
+               o2hb_set_quorum_device(reg);
+               o2hb_arm_write_timeout(reg);
+       }
 
+bail:
        /* let the person who launched us know when things are steady */
-       if (!change && (atomic_read(&reg->hr_steady_iterations) != 0)) {
-               if (atomic_dec_and_test(&reg->hr_steady_iterations))
+       if (atomic_read(&reg->hr_steady_iterations) != 0) {
+               if (!ret && own_slot_ok && !membership_change) {
+                       if (atomic_dec_and_test(&reg->hr_steady_iterations))
+                               wake_up(&o2hb_steady_queue);
+               }
+       }
+
+       if (atomic_read(&reg->hr_steady_iterations) != 0) {
+               if (atomic_dec_and_test(&reg->hr_unsteady_iterations)) {
+                       printk(KERN_NOTICE "o2hb: Unable to stabilize "
+                              "heartbeart on region %s (%s)\n",
+                              config_item_name(&reg->hr_item),
+                              reg->hr_dev_name);
+                       atomic_set(&reg->hr_steady_iterations, 0);
+                       reg->hr_aborted_start = 1;
                        wake_up(&o2hb_steady_queue);
+                       ret = -EIO;
+               }
        }
 
-       return 0;
+       return ret;
 }
 
 /* Subtract b from a, storing the result in a. a *must* have a larger
@@ -1095,7 +1136,8 @@ static int o2hb_thread(void *data)
        /* Pin node */
        o2nm_depend_this_node();
 
-       while (!kthread_should_stop() && !reg->hr_unclean_stop) {
+       while (!kthread_should_stop() &&
+              !reg->hr_unclean_stop && !reg->hr_aborted_start) {
                /* We track the time spent inside
                 * o2hb_do_disk_heartbeat so that we avoid more than
                 * hr_timeout_ms between disk writes. On busy systems
@@ -1103,10 +1145,7 @@ static int o2hb_thread(void *data)
                 * likely to time itself out. */
                do_gettimeofday(&before_hb);
 
-               i = 0;
-               do {
-                       ret = o2hb_do_disk_heartbeat(reg);
-               } while (ret && ++i < 2);
+               ret = o2hb_do_disk_heartbeat(reg);
 
                do_gettimeofday(&after_hb);
                elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb);
@@ -1117,7 +1156,8 @@ static int o2hb_thread(void *data)
                     after_hb.tv_sec, (unsigned long) after_hb.tv_usec,
                     elapsed_msec);
 
-               if (elapsed_msec < reg->hr_timeout_ms) {
+               if (!kthread_should_stop() &&
+                   elapsed_msec < reg->hr_timeout_ms) {
                        /* the kthread api has blocked signals for us so no
                         * need to record the return value. */
                        msleep_interruptible(reg->hr_timeout_ms - elapsed_msec);
@@ -1134,20 +1174,20 @@ static int o2hb_thread(void *data)
         * to timeout on this region when we could just as easily
         * write a clear generation - thus indicating to them that
         * this node has left this region.
-        *
-        * XXX: Should we skip this on unclean_stop? */
-       o2hb_prepare_block(reg, 0);
-       ret = o2hb_issue_node_write(reg, &write_wc);
-       if (ret == 0) {
-               o2hb_wait_on_io(reg, &write_wc);
-       } else {
-               mlog_errno(ret);
+        */
+       if (!reg->hr_unclean_stop && !reg->hr_aborted_start) {
+               o2hb_prepare_block(reg, 0);
+               ret = o2hb_issue_node_write(reg, &write_wc);
+               if (ret == 0)
+                       o2hb_wait_on_io(reg, &write_wc);
+               else
+                       mlog_errno(ret);
        }
 
        /* Unpin node */
        o2nm_undepend_this_node();
 
-       mlog(ML_HEARTBEAT|ML_KTHREAD, "hb thread exiting\n");
+       mlog(ML_HEARTBEAT|ML_KTHREAD, "o2hb thread exiting\n");
 
        return 0;
 }
@@ -1158,6 +1198,7 @@ static int o2hb_debug_open(struct inode *inode, struct file *file)
        struct o2hb_debug_buf *db = inode->i_private;
        struct o2hb_region *reg;
        unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+       unsigned long lts;
        char *buf = NULL;
        int i = -1;
        int out = 0;
@@ -1194,9 +1235,11 @@ static int o2hb_debug_open(struct inode *inode, struct file *file)
 
        case O2HB_DB_TYPE_REGION_ELAPSED_TIME:
                reg = (struct o2hb_region *)db->db_data;
-               out += snprintf(buf + out, PAGE_SIZE - out, "%u\n",
-                               jiffies_to_msecs(jiffies -
-                                                reg->hr_last_timeout_start));
+               lts = reg->hr_last_timeout_start;
+               /* If 0, it has never been set before */
+               if (lts)
+                       lts = jiffies_to_msecs(jiffies - lts);
+               out += snprintf(buf + out, PAGE_SIZE - out, "%lu\n", lts);
                goto done;
 
        case O2HB_DB_TYPE_REGION_PINNED:
@@ -1426,6 +1469,8 @@ static void o2hb_region_release(struct config_item *item)
        struct page *page;
        struct o2hb_region *reg = to_o2hb_region(item);
 
+       mlog(ML_HEARTBEAT, "hb region release (%s)\n", reg->hr_dev_name);
+
        if (reg->hr_tmp_block)
                kfree(reg->hr_tmp_block);
 
@@ -1792,7 +1837,10 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
                        live_threshold <<= 1;
                spin_unlock(&o2hb_live_lock);
        }
-       atomic_set(&reg->hr_steady_iterations, live_threshold + 1);
+       ++live_threshold;
+       atomic_set(&reg->hr_steady_iterations, live_threshold);
+       /* unsteady_iterations is double the steady_iterations */
+       atomic_set(&reg->hr_unsteady_iterations, (live_threshold << 1));
 
        hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s",
                              reg->hr_item.ci_name);
@@ -1809,14 +1857,12 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        ret = wait_event_interruptible(o2hb_steady_queue,
                                atomic_read(&reg->hr_steady_iterations) == 0);
        if (ret) {
-               /* We got interrupted (hello ptrace!).  Clean up */
-               spin_lock(&o2hb_live_lock);
-               hb_task = reg->hr_task;
-               reg->hr_task = NULL;
-               spin_unlock(&o2hb_live_lock);
+               atomic_set(&reg->hr_steady_iterations, 0);
+               reg->hr_aborted_start = 1;
+       }
 
-               if (hb_task)
-                       kthread_stop(hb_task);
+       if (reg->hr_aborted_start) {
+               ret = -EIO;
                goto out;
        }
 
@@ -1833,8 +1879,8 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
                ret = -EIO;
 
        if (hb_task && o2hb_global_heartbeat_active())
-               printk(KERN_NOTICE "o2hb: Heartbeat started on region %s\n",
-                      config_item_name(&reg->hr_item));
+               printk(KERN_NOTICE "o2hb: Heartbeat started on region %s (%s)\n",
+                      config_item_name(&reg->hr_item), reg->hr_dev_name);
 
 out:
        if (filp)
@@ -2092,13 +2138,6 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
 
        /* stop the thread when the user removes the region dir */
        spin_lock(&o2hb_live_lock);
-       if (o2hb_global_heartbeat_active()) {
-               clear_bit(reg->hr_region_num, o2hb_region_bitmap);
-               clear_bit(reg->hr_region_num, o2hb_live_region_bitmap);
-               if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
-                       quorum_region = 1;
-               clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap);
-       }
        hb_task = reg->hr_task;
        reg->hr_task = NULL;
        reg->hr_item_dropped = 1;
@@ -2107,19 +2146,30 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
        if (hb_task)
                kthread_stop(hb_task);
 
+       if (o2hb_global_heartbeat_active()) {
+               spin_lock(&o2hb_live_lock);
+               clear_bit(reg->hr_region_num, o2hb_region_bitmap);
+               clear_bit(reg->hr_region_num, o2hb_live_region_bitmap);
+               if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+                       quorum_region = 1;
+               clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap);
+               spin_unlock(&o2hb_live_lock);
+               printk(KERN_NOTICE "o2hb: Heartbeat %s on region %s (%s)\n",
+                      ((atomic_read(&reg->hr_steady_iterations) == 0) ?
+                       "stopped" : "start aborted"), config_item_name(item),
+                      reg->hr_dev_name);
+       }
+
        /*
         * If we're racing a dev_write(), we need to wake them.  They will
         * check reg->hr_task
         */
        if (atomic_read(&reg->hr_steady_iterations) != 0) {
+               reg->hr_aborted_start = 1;
                atomic_set(&reg->hr_steady_iterations, 0);
                wake_up(&o2hb_steady_queue);
        }
 
-       if (o2hb_global_heartbeat_active())
-               printk(KERN_NOTICE "o2hb: Heartbeat stopped on region %s\n",
-                      config_item_name(&reg->hr_item));
-
        config_item_put(item);
 
        if (!o2hb_global_heartbeat_active() || !quorum_region)
index 3a5835904b3db4d522c561908171f528bb74f6bd..dc45deb19e6885e56a1f5be46cbd39444c46f810 100644 (file)
@@ -47,6 +47,7 @@
 #define SC_DEBUG_NAME          "sock_containers"
 #define NST_DEBUG_NAME         "send_tracking"
 #define STATS_DEBUG_NAME       "stats"
+#define NODES_DEBUG_NAME       "connected_nodes"
 
 #define SHOW_SOCK_CONTAINERS   0
 #define SHOW_SOCK_STATS                1
@@ -55,6 +56,7 @@ static struct dentry *o2net_dentry;
 static struct dentry *sc_dentry;
 static struct dentry *nst_dentry;
 static struct dentry *stats_dentry;
+static struct dentry *nodes_dentry;
 
 static DEFINE_SPINLOCK(o2net_debug_lock);
 
@@ -491,53 +493,87 @@ static const struct file_operations sc_seq_fops = {
        .release = sc_fop_release,
 };
 
-int o2net_debugfs_init(void)
+static int o2net_fill_bitmap(char *buf, int len)
 {
-       o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL);
-       if (!o2net_dentry) {
-               mlog_errno(-ENOMEM);
-               goto bail;
-       }
+       unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+       int i = -1, out = 0;
 
-       nst_dentry = debugfs_create_file(NST_DEBUG_NAME, S_IFREG|S_IRUSR,
-                                        o2net_dentry, NULL,
-                                        &nst_seq_fops);
-       if (!nst_dentry) {
-               mlog_errno(-ENOMEM);
-               goto bail;
-       }
+       o2net_fill_node_map(map, sizeof(map));
 
-       sc_dentry = debugfs_create_file(SC_DEBUG_NAME, S_IFREG|S_IRUSR,
-                                       o2net_dentry, NULL,
-                                       &sc_seq_fops);
-       if (!sc_dentry) {
-               mlog_errno(-ENOMEM);
-               goto bail;
-       }
+       while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES)
+               out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i);
+       out += snprintf(buf + out, PAGE_SIZE - out, "\n");
 
-       stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, S_IFREG|S_IRUSR,
-                                          o2net_dentry, NULL,
-                                          &stats_seq_fops);
-       if (!stats_dentry) {
-               mlog_errno(-ENOMEM);
-               goto bail;
-       }
+       return out;
+}
+
+static int nodes_fop_open(struct inode *inode, struct file *file)
+{
+       char *buf;
+
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       i_size_write(inode, o2net_fill_bitmap(buf, PAGE_SIZE));
+
+       file->private_data = buf;
 
        return 0;
-bail:
-       debugfs_remove(stats_dentry);
-       debugfs_remove(sc_dentry);
-       debugfs_remove(nst_dentry);
-       debugfs_remove(o2net_dentry);
-       return -ENOMEM;
 }
 
+static int o2net_debug_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       return 0;
+}
+
+static ssize_t o2net_debug_read(struct file *file, char __user *buf,
+                               size_t nbytes, loff_t *ppos)
+{
+       return simple_read_from_buffer(buf, nbytes, ppos, file->private_data,
+                                      i_size_read(file->f_mapping->host));
+}
+
+static const struct file_operations nodes_fops = {
+       .open           = nodes_fop_open,
+       .release        = o2net_debug_release,
+       .read           = o2net_debug_read,
+       .llseek         = generic_file_llseek,
+};
+
 void o2net_debugfs_exit(void)
 {
+       debugfs_remove(nodes_dentry);
        debugfs_remove(stats_dentry);
        debugfs_remove(sc_dentry);
        debugfs_remove(nst_dentry);
        debugfs_remove(o2net_dentry);
 }
 
+int o2net_debugfs_init(void)
+{
+       mode_t mode = S_IFREG|S_IRUSR;
+
+       o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL);
+       if (o2net_dentry)
+               nst_dentry = debugfs_create_file(NST_DEBUG_NAME, mode,
+                                       o2net_dentry, NULL, &nst_seq_fops);
+       if (nst_dentry)
+               sc_dentry = debugfs_create_file(SC_DEBUG_NAME, mode,
+                                       o2net_dentry, NULL, &sc_seq_fops);
+       if (sc_dentry)
+               stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, mode,
+                                       o2net_dentry, NULL, &stats_seq_fops);
+       if (stats_dentry)
+               nodes_dentry = debugfs_create_file(NODES_DEBUG_NAME, mode,
+                                       o2net_dentry, NULL, &nodes_fops);
+       if (nodes_dentry)
+               return 0;
+
+       o2net_debugfs_exit();
+       mlog_errno(-ENOMEM);
+       return -ENOMEM;
+}
+
 #endif /* CONFIG_DEBUG_FS */
index ad7d0c155de41a3912b5a6fa330b28ca48edf790..044e7b58d31c7662a75e29f636cfb86bf2846b67 100644 (file)
@@ -546,7 +546,7 @@ static void o2net_set_nn_state(struct o2net_node *nn,
        }
 
        if (was_valid && !valid) {
-               printk(KERN_NOTICE "o2net: no longer connected to "
+               printk(KERN_NOTICE "o2net: No longer connected to "
                       SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc));
                o2net_complete_nodes_nsw(nn);
        }
@@ -556,7 +556,7 @@ static void o2net_set_nn_state(struct o2net_node *nn,
                cancel_delayed_work(&nn->nn_connect_expired);
                printk(KERN_NOTICE "o2net: %s " SC_NODEF_FMT "\n",
                       o2nm_this_node() > sc->sc_node->nd_num ?
-                               "connected to" : "accepted connection from",
+                      "Connected to" : "Accepted connection from",
                       SC_NODEF_ARGS(sc));
        }
 
@@ -644,7 +644,7 @@ static void o2net_state_change(struct sock *sk)
                        o2net_sc_queue_work(sc, &sc->sc_connect_work);
                        break;
                default:
-                       printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT
+                       printk(KERN_INFO "o2net: Connection to " SC_NODEF_FMT
                              " shutdown, state %d\n",
                              SC_NODEF_ARGS(sc), sk->sk_state);
                        o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
@@ -1035,6 +1035,25 @@ static int o2net_tx_can_proceed(struct o2net_node *nn,
        return ret;
 }
 
+/* Get a map of all nodes to which this node is currently connected to */
+void o2net_fill_node_map(unsigned long *map, unsigned bytes)
+{
+       struct o2net_sock_container *sc;
+       int node, ret;
+
+       BUG_ON(bytes < (BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof(unsigned long)));
+
+       memset(map, 0, bytes);
+       for (node = 0; node < O2NM_MAX_NODES; ++node) {
+               o2net_tx_can_proceed(o2net_nn_from_num(node), &sc, &ret);
+               if (!ret) {
+                       set_bit(node, map);
+                       sc_put(sc);
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(o2net_fill_node_map);
+
 int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
                           size_t caller_veclen, u8 target_node, int *status)
 {
@@ -1285,11 +1304,11 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
        struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
 
        if (hand->protocol_version != cpu_to_be64(O2NET_PROTOCOL_VERSION)) {
-               mlog(ML_NOTICE, SC_NODEF_FMT " advertised net protocol "
-                    "version %llu but %llu is required, disconnecting\n",
-                    SC_NODEF_ARGS(sc),
-                    (unsigned long long)be64_to_cpu(hand->protocol_version),
-                    O2NET_PROTOCOL_VERSION);
+               printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " Advertised net "
+                      "protocol version %llu but %llu is required. "
+                      "Disconnecting.\n", SC_NODEF_ARGS(sc),
+                      (unsigned long long)be64_to_cpu(hand->protocol_version),
+                      O2NET_PROTOCOL_VERSION);
 
                /* don't bother reconnecting if its the wrong version. */
                o2net_ensure_shutdown(nn, sc, -ENOTCONN);
@@ -1303,33 +1322,33 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
         */
        if (be32_to_cpu(hand->o2net_idle_timeout_ms) !=
                                o2net_idle_timeout()) {
-               mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of "
-                    "%u ms, but we use %u ms locally.  disconnecting\n",
-                    SC_NODEF_ARGS(sc),
-                    be32_to_cpu(hand->o2net_idle_timeout_ms),
-                    o2net_idle_timeout());
+               printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a network "
+                      "idle timeout of %u ms, but we use %u ms locally. "
+                      "Disconnecting.\n", SC_NODEF_ARGS(sc),
+                      be32_to_cpu(hand->o2net_idle_timeout_ms),
+                      o2net_idle_timeout());
                o2net_ensure_shutdown(nn, sc, -ENOTCONN);
                return -1;
        }
 
        if (be32_to_cpu(hand->o2net_keepalive_delay_ms) !=
                        o2net_keepalive_delay()) {
-               mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of "
-                    "%u ms, but we use %u ms locally.  disconnecting\n",
-                    SC_NODEF_ARGS(sc),
-                    be32_to_cpu(hand->o2net_keepalive_delay_ms),
-                    o2net_keepalive_delay());
+               printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a keepalive "
+                      "delay of %u ms, but we use %u ms locally. "
+                      "Disconnecting.\n", SC_NODEF_ARGS(sc),
+                      be32_to_cpu(hand->o2net_keepalive_delay_ms),
+                      o2net_keepalive_delay());
                o2net_ensure_shutdown(nn, sc, -ENOTCONN);
                return -1;
        }
 
        if (be32_to_cpu(hand->o2hb_heartbeat_timeout_ms) !=
                        O2HB_MAX_WRITE_TIMEOUT_MS) {
-               mlog(ML_NOTICE, SC_NODEF_FMT " uses a heartbeat timeout of "
-                    "%u ms, but we use %u ms locally.  disconnecting\n",
-                    SC_NODEF_ARGS(sc),
-                    be32_to_cpu(hand->o2hb_heartbeat_timeout_ms),
-                    O2HB_MAX_WRITE_TIMEOUT_MS);
+               printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a heartbeat "
+                      "timeout of %u ms, but we use %u ms locally. "
+                      "Disconnecting.\n", SC_NODEF_ARGS(sc),
+                      be32_to_cpu(hand->o2hb_heartbeat_timeout_ms),
+                      O2HB_MAX_WRITE_TIMEOUT_MS);
                o2net_ensure_shutdown(nn, sc, -ENOTCONN);
                return -1;
        }
@@ -1540,28 +1559,16 @@ static void o2net_idle_timer(unsigned long data)
 {
        struct o2net_sock_container *sc = (struct o2net_sock_container *)data;
        struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
-
 #ifdef CONFIG_DEBUG_FS
-       ktime_t now = ktime_get();
+       unsigned long msecs = ktime_to_ms(ktime_get()) -
+               ktime_to_ms(sc->sc_tv_timer);
+#else
+       unsigned long msecs = o2net_idle_timeout();
 #endif
 
-       printk(KERN_NOTICE "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u "
-            "seconds, shutting it down.\n", SC_NODEF_ARGS(sc),
-                    o2net_idle_timeout() / 1000,
-                    o2net_idle_timeout() % 1000);
-
-#ifdef CONFIG_DEBUG_FS
-       mlog(ML_NOTICE, "Here are some times that might help debug the "
-            "situation: (Timer: %lld, Now %lld, DataReady %lld, Advance %lld-%lld, "
-            "Key 0x%08x, Func %u, FuncTime %lld-%lld)\n",
-            (long long)ktime_to_us(sc->sc_tv_timer), (long long)ktime_to_us(now),
-            (long long)ktime_to_us(sc->sc_tv_data_ready),
-            (long long)ktime_to_us(sc->sc_tv_advance_start),
-            (long long)ktime_to_us(sc->sc_tv_advance_stop),
-            sc->sc_msg_key, sc->sc_msg_type,
-            (long long)ktime_to_us(sc->sc_tv_func_start),
-            (long long)ktime_to_us(sc->sc_tv_func_stop));
-#endif
+       printk(KERN_NOTICE "o2net: Connection to " SC_NODEF_FMT " has been "
+              "idle for %lu.%lu secs, shutting it down.\n", SC_NODEF_ARGS(sc),
+              msecs / 1000, msecs % 1000);
 
        /*
         * Initialize the nn_timeout so that the next connection attempt
@@ -1694,8 +1701,8 @@ static void o2net_start_connect(struct work_struct *work)
 
 out:
        if (ret) {
-               mlog(ML_NOTICE, "connect attempt to " SC_NODEF_FMT " failed "
-                    "with errno %d\n", SC_NODEF_ARGS(sc), ret);
+               printk(KERN_NOTICE "o2net: Connect attempt to " SC_NODEF_FMT
+                      " failed with errno %d\n", SC_NODEF_ARGS(sc), ret);
                /* 0 err so that another will be queued and attempted
                 * from set_nn_state */
                if (sc)
@@ -1718,8 +1725,8 @@ static void o2net_connect_expired(struct work_struct *work)
 
        spin_lock(&nn->nn_lock);
        if (!nn->nn_sc_valid) {
-               mlog(ML_ERROR, "no connection established with node %u after "
-                    "%u.%u seconds, giving up and returning errors.\n",
+               printk(KERN_NOTICE "o2net: No connection established with "
+                      "node %u after %u.%u seconds, giving up.\n",
                     o2net_num_from_nn(nn),
                     o2net_idle_timeout() / 1000,
                     o2net_idle_timeout() % 1000);
@@ -1862,21 +1869,21 @@ static int o2net_accept_one(struct socket *sock)
 
        node = o2nm_get_node_by_ip(sin.sin_addr.s_addr);
        if (node == NULL) {
-               mlog(ML_NOTICE, "attempt to connect from unknown node at %pI4:%d\n",
-                    &sin.sin_addr.s_addr, ntohs(sin.sin_port));
+               printk(KERN_NOTICE "o2net: Attempt to connect from unknown "
+                      "node at %pI4:%d\n", &sin.sin_addr.s_addr,
+                      ntohs(sin.sin_port));
                ret = -EINVAL;
                goto out;
        }
 
        if (o2nm_this_node() >= node->nd_num) {
                local_node = o2nm_get_node_by_num(o2nm_this_node());
-               mlog(ML_NOTICE, "unexpected connect attempt seen at node '%s' ("
-                    "%u, %pI4:%d) from node '%s' (%u, %pI4:%d)\n",
-                    local_node->nd_name, local_node->nd_num,
-                    &(local_node->nd_ipv4_address),
-                    ntohs(local_node->nd_ipv4_port),
-                    node->nd_name, node->nd_num, &sin.sin_addr.s_addr,
-                    ntohs(sin.sin_port));
+               printk(KERN_NOTICE "o2net: Unexpected connect attempt seen "
+                      "at node '%s' (%u, %pI4:%d) from node '%s' (%u, "
+                      "%pI4:%d)\n", local_node->nd_name, local_node->nd_num,
+                      &(local_node->nd_ipv4_address),
+                      ntohs(local_node->nd_ipv4_port), node->nd_name,
+                      node->nd_num, &sin.sin_addr.s_addr, ntohs(sin.sin_port));
                ret = -EINVAL;
                goto out;
        }
@@ -1901,10 +1908,10 @@ static int o2net_accept_one(struct socket *sock)
                ret = 0;
        spin_unlock(&nn->nn_lock);
        if (ret) {
-               mlog(ML_NOTICE, "attempt to connect from node '%s' at "
-                    "%pI4:%d but it already has an open connection\n",
-                    node->nd_name, &sin.sin_addr.s_addr,
-                    ntohs(sin.sin_port));
+               printk(KERN_NOTICE "o2net: Attempt to connect from node '%s' "
+                      "at %pI4:%d but it already has an open connection\n",
+                      node->nd_name, &sin.sin_addr.s_addr,
+                      ntohs(sin.sin_port));
                goto out;
        }
 
@@ -1984,7 +1991,7 @@ static int o2net_open_listening_sock(__be32 addr, __be16 port)
 
        ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
        if (ret < 0) {
-               mlog(ML_ERROR, "unable to create socket, ret=%d\n", ret);
+               printk(KERN_ERR "o2net: Error %d while creating socket\n", ret);
                goto out;
        }
 
@@ -2001,16 +2008,15 @@ static int o2net_open_listening_sock(__be32 addr, __be16 port)
        sock->sk->sk_reuse = 1;
        ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin));
        if (ret < 0) {
-               mlog(ML_ERROR, "unable to bind socket at %pI4:%u, "
-                    "ret=%d\n", &addr, ntohs(port), ret);
+               printk(KERN_ERR "o2net: Error %d while binding socket at "
+                      "%pI4:%u\n", ret, &addr, ntohs(port)); 
                goto out;
        }
 
        ret = sock->ops->listen(sock, 64);
-       if (ret < 0) {
-               mlog(ML_ERROR, "unable to listen on %pI4:%u, ret=%d\n",
-                    &addr, ntohs(port), ret);
-       }
+       if (ret < 0)
+               printk(KERN_ERR "o2net: Error %d while listening on %pI4:%u\n",
+                      ret, &addr, ntohs(port));
 
 out:
        if (ret) {
index fd6179eb26d4cd2cfb43f4ff053237837712113e..5bada2a69b503cd365d626a25e4ae6d08ad50b7a 100644 (file)
@@ -106,6 +106,8 @@ int o2net_register_handler(u32 msg_type, u32 key, u32 max_len,
                           struct list_head *unreg_list);
 void o2net_unregister_handler_list(struct list_head *list);
 
+void o2net_fill_node_map(unsigned long *map, unsigned bytes);
+
 struct o2nm_node;
 int o2net_register_hb_callbacks(void);
 void o2net_unregister_hb_callbacks(void);
index e2878b5895fb543a86c11f0128b025dbb0335c38..8fe4e2892ab9ccd983304a825c338df57a5376b8 100644 (file)
@@ -1184,8 +1184,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
                        if (pde)
                                le16_add_cpu(&pde->rec_len,
                                                le16_to_cpu(de->rec_len));
-                       else
-                               de->inode = 0;
+                       de->inode = 0;
                        dir->i_version++;
                        ocfs2_journal_dirty(handle, bh);
                        goto bail;
index d602abb51b610d525cc437daa05c25d2105fe0c3..a5952ceecba5a83147389ad4a1cd24972ee0bfbe 100644 (file)
@@ -859,8 +859,8 @@ void dlm_complete_recovery_thread(struct dlm_ctxt *dlm);
 void dlm_wait_for_recovery(struct dlm_ctxt *dlm);
 void dlm_kick_recovery_thread(struct dlm_ctxt *dlm);
 int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node);
-int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout);
-int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout);
+void dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout);
+void dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout);
 
 void dlm_put(struct dlm_ctxt *dlm);
 struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm);
@@ -877,9 +877,8 @@ static inline void dlm_lockres_get(struct dlm_lock_resource *res)
        kref_get(&res->refs);
 }
 void dlm_lockres_put(struct dlm_lock_resource *res);
-void __dlm_unhash_lockres(struct dlm_lock_resource *res);
-void __dlm_insert_lockres(struct dlm_ctxt *dlm,
-                         struct dlm_lock_resource *res);
+void __dlm_unhash_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
+void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
 struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
                                                     const char *name,
                                                     unsigned int len,
@@ -902,46 +901,15 @@ struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm,
                                          const char *name,
                                          unsigned int namelen);
 
-#define dlm_lockres_set_refmap_bit(bit,res)  \
-       __dlm_lockres_set_refmap_bit(bit,res,__FILE__,__LINE__)
-#define dlm_lockres_clear_refmap_bit(bit,res)  \
-       __dlm_lockres_clear_refmap_bit(bit,res,__FILE__,__LINE__)
+void dlm_lockres_set_refmap_bit(struct dlm_ctxt *dlm,
+                               struct dlm_lock_resource *res, int bit);
+void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm,
+                                 struct dlm_lock_resource *res, int bit);
 
-static inline void __dlm_lockres_set_refmap_bit(int bit,
-                                               struct dlm_lock_resource *res,
-                                               const char *file,
-                                               int line)
-{
-       //printk("%s:%d:%.*s: setting bit %d\n", file, line,
-       //     res->lockname.len, res->lockname.name, bit);
-       set_bit(bit, res->refmap);
-}
-
-static inline void __dlm_lockres_clear_refmap_bit(int bit,
-                                                 struct dlm_lock_resource *res,
-                                                 const char *file,
-                                                 int line)
-{
-       //printk("%s:%d:%.*s: clearing bit %d\n", file, line,
-       //     res->lockname.len, res->lockname.name, bit);
-       clear_bit(bit, res->refmap);
-}
-
-void __dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
-                                  struct dlm_lock_resource *res,
-                                  const char *file,
-                                  int line);
-void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
-                                  struct dlm_lock_resource *res,
-                                  int new_lockres,
-                                  const char *file,
-                                  int line);
-#define dlm_lockres_drop_inflight_ref(d,r)  \
-       __dlm_lockres_drop_inflight_ref(d,r,__FILE__,__LINE__)
-#define dlm_lockres_grab_inflight_ref(d,r)  \
-       __dlm_lockres_grab_inflight_ref(d,r,0,__FILE__,__LINE__)
-#define dlm_lockres_grab_inflight_ref_new(d,r)  \
-       __dlm_lockres_grab_inflight_ref(d,r,1,__FILE__,__LINE__)
+void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
+                                  struct dlm_lock_resource *res);
+void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
+                                  struct dlm_lock_resource *res);
 
 void dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
 void dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
index 6ed6b95dcf935a6516e935b85a3ca9ffc0b8a9d8..92f2ead0fab6de22fa138cc4410dee6e1544216c 100644 (file)
@@ -157,16 +157,18 @@ static int dlm_protocol_compare(struct dlm_protocol_version *existing,
 
 static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm);
 
-void __dlm_unhash_lockres(struct dlm_lock_resource *lockres)
+void __dlm_unhash_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
 {
-       if (!hlist_unhashed(&lockres->hash_node)) {
-               hlist_del_init(&lockres->hash_node);
-               dlm_lockres_put(lockres);
-       }
+       if (hlist_unhashed(&res->hash_node))
+               return;
+
+       mlog(0, "%s: Unhash res %.*s\n", dlm->name, res->lockname.len,
+            res->lockname.name);
+       hlist_del_init(&res->hash_node);
+       dlm_lockres_put(res);
 }
 
-void __dlm_insert_lockres(struct dlm_ctxt *dlm,
-                      struct dlm_lock_resource *res)
+void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
 {
        struct hlist_head *bucket;
        struct qstr *q;
@@ -180,6 +182,9 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm,
        dlm_lockres_get(res);
 
        hlist_add_head(&res->hash_node, bucket);
+
+       mlog(0, "%s: Hash res %.*s\n", dlm->name, res->lockname.len,
+            res->lockname.name);
 }
 
 struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
@@ -539,17 +544,17 @@ again:
 
 static void __dlm_print_nodes(struct dlm_ctxt *dlm)
 {
-       int node = -1;
+       int node = -1, num = 0;
 
        assert_spin_locked(&dlm->spinlock);
 
-       printk(KERN_NOTICE "o2dlm: Nodes in domain %s: ", dlm->name);
-
+       printk("( ");
        while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES,
                                     node + 1)) < O2NM_MAX_NODES) {
                printk("%d ", node);
+               ++num;
        }
-       printk("\n");
+       printk(") %u nodes\n", num);
 }
 
 static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
@@ -566,11 +571,10 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
 
        node = exit_msg->node_idx;
 
-       printk(KERN_NOTICE "o2dlm: Node %u leaves domain %s\n", node, dlm->name);
-
        spin_lock(&dlm->spinlock);
        clear_bit(node, dlm->domain_map);
        clear_bit(node, dlm->exit_domain_map);
+       printk(KERN_NOTICE "o2dlm: Node %u leaves domain %s ", node, dlm->name);
        __dlm_print_nodes(dlm);
 
        /* notify anything attached to the heartbeat events */
@@ -755,6 +759,7 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
 
                dlm_mark_domain_leaving(dlm);
                dlm_leave_domain(dlm);
+               printk(KERN_NOTICE "o2dlm: Leaving domain %s\n", dlm->name);
                dlm_force_free_mles(dlm);
                dlm_complete_dlm_shutdown(dlm);
        }
@@ -970,7 +975,7 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
                clear_bit(assert->node_idx, dlm->exit_domain_map);
                __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
 
-               printk(KERN_NOTICE "o2dlm: Node %u joins domain %s\n",
+               printk(KERN_NOTICE "o2dlm: Node %u joins domain %s ",
                       assert->node_idx, dlm->name);
                __dlm_print_nodes(dlm);
 
@@ -1701,8 +1706,10 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
 bail:
        spin_lock(&dlm->spinlock);
        __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
-       if (!status)
+       if (!status) {
+               printk(KERN_NOTICE "o2dlm: Joining domain %s ", dlm->name);
                __dlm_print_nodes(dlm);
+       }
        spin_unlock(&dlm->spinlock);
 
        if (ctxt) {
@@ -2131,13 +2138,6 @@ struct dlm_ctxt * dlm_register_domain(const char *domain,
                goto leave;
        }
 
-       if (!o2hb_check_local_node_heartbeating()) {
-               mlog(ML_ERROR, "the local node has not been configured, or is "
-                    "not heartbeating\n");
-               ret = -EPROTO;
-               goto leave;
-       }
-
        mlog(0, "register called for domain \"%s\"\n", domain);
 
 retry:
index 8d39e0fd66f7379b8fb08ac40502efa0d4a51cc6..975810b98492a34f4576b9d3d3ac3e4421fb18c1 100644 (file)
@@ -183,10 +183,6 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm,
                        kick_thread = 1;
                }
        }
-       /* reduce the inflight count, this may result in the lockres
-        * being purged below during calc_usage */
-       if (lock->ml.node == dlm->node_num)
-               dlm_lockres_drop_inflight_ref(dlm, res);
 
        spin_unlock(&res->spinlock);
        wake_up(&res->wq);
@@ -231,10 +227,16 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm,
             lock->ml.type, res->lockname.len,
             res->lockname.name, flags);
 
+       /*
+        * Wait if resource is getting recovered, remastered, etc.
+        * If the resource was remastered and new owner is self, then exit.
+        */
        spin_lock(&res->spinlock);
-
-       /* will exit this call with spinlock held */
        __dlm_wait_on_lockres(res);
+       if (res->owner == dlm->node_num) {
+               spin_unlock(&res->spinlock);
+               return DLM_RECOVERING;
+       }
        res->state |= DLM_LOCK_RES_IN_PROGRESS;
 
        /* add lock to local (secondary) queue */
@@ -319,27 +321,23 @@ static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm,
        tmpret = o2net_send_message(DLM_CREATE_LOCK_MSG, dlm->key, &create,
                                    sizeof(create), res->owner, &status);
        if (tmpret >= 0) {
-               // successfully sent and received
-               ret = status;  // this is already a dlm_status
+               ret = status;
                if (ret == DLM_REJECTED) {
-                       mlog(ML_ERROR, "%s:%.*s: BUG.  this is a stale lockres "
-                            "no longer owned by %u.  that node is coming back "
-                            "up currently.\n", dlm->name, create.namelen,
+                       mlog(ML_ERROR, "%s: res %.*s, Stale lockres no longer "
+                            "owned by node %u. That node is coming back up "
+                            "currently.\n", dlm->name, create.namelen,
                             create.name, res->owner);
                        dlm_print_one_lock_resource(res);
                        BUG();
                }
        } else {
-               mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to "
-                    "node %u\n", tmpret, DLM_CREATE_LOCK_MSG, dlm->key,
-                    res->owner);
-               if (dlm_is_host_down(tmpret)) {
+               mlog(ML_ERROR, "%s: res %.*s, Error %d send CREATE LOCK to "
+                    "node %u\n", dlm->name, create.namelen, create.name,
+                    tmpret, res->owner);
+               if (dlm_is_host_down(tmpret))
                        ret = DLM_RECOVERING;
-                       mlog(0, "node %u died so returning DLM_RECOVERING "
-                            "from lock message!\n", res->owner);
-               } else {
+               else
                        ret = dlm_err_to_dlm_status(tmpret);
-               }
        }
 
        return ret;
@@ -440,7 +438,7 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
                /* zero memory only if kernel-allocated */
                lksb = kzalloc(sizeof(*lksb), GFP_NOFS);
                if (!lksb) {
-                       kfree(lock);
+                       kmem_cache_free(dlm_lock_cache, lock);
                        return NULL;
                }
                kernel_allocated = 1;
@@ -718,18 +716,10 @@ retry_lock:
 
                if (status == DLM_RECOVERING || status == DLM_MIGRATING ||
                    status == DLM_FORWARD) {
-                       mlog(0, "retrying lock with migration/"
-                            "recovery/in progress\n");
                        msleep(100);
-                       /* no waiting for dlm_reco_thread */
                        if (recovery) {
                                if (status != DLM_RECOVERING)
                                        goto retry_lock;
-
-                               mlog(0, "%s: got RECOVERING "
-                                    "for $RECOVERY lock, master "
-                                    "was %u\n", dlm->name,
-                                    res->owner);
                                /* wait to see the node go down, then
                                 * drop down and allow the lockres to
                                 * get cleaned up.  need to remaster. */
@@ -741,6 +731,14 @@ retry_lock:
                        }
                }
 
+               /* Inflight taken in dlm_get_lock_resource() is dropped here */
+               spin_lock(&res->spinlock);
+               dlm_lockres_drop_inflight_ref(dlm, res);
+               spin_unlock(&res->spinlock);
+
+               dlm_lockres_calc_usage(dlm, res);
+               dlm_kick_thread(dlm, res);
+
                if (status != DLM_NORMAL) {
                        lock->lksb->flags &= ~DLM_LKSB_GET_LVB;
                        if (status != DLM_NOTQUEUED)
index 11eefb8c12e98fb418f41c31a3b0a32201be3ca1..005261c333b090f5f53f376bd5bbed55b8e16ba7 100644 (file)
@@ -631,39 +631,54 @@ error:
        return NULL;
 }
 
-void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
-                                  struct dlm_lock_resource *res,
-                                  int new_lockres,
-                                  const char *file,
-                                  int line)
+void dlm_lockres_set_refmap_bit(struct dlm_ctxt *dlm,
+                               struct dlm_lock_resource *res, int bit)
 {
-       if (!new_lockres)
-               assert_spin_locked(&res->spinlock);
+       assert_spin_locked(&res->spinlock);
+
+       mlog(0, "res %.*s, set node %u, %ps()\n", res->lockname.len,
+            res->lockname.name, bit, __builtin_return_address(0));
+
+       set_bit(bit, res->refmap);
+}
+
+void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm,
+                                 struct dlm_lock_resource *res, int bit)
+{
+       assert_spin_locked(&res->spinlock);
+
+       mlog(0, "res %.*s, clr node %u, %ps()\n", res->lockname.len,
+            res->lockname.name, bit, __builtin_return_address(0));
+
+       clear_bit(bit, res->refmap);
+}
+
+
+void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
+                                  struct dlm_lock_resource *res)
+{
+       assert_spin_locked(&res->spinlock);
 
-       if (!test_bit(dlm->node_num, res->refmap)) {
-               BUG_ON(res->inflight_locks != 0);
-               dlm_lockres_set_refmap_bit(dlm->node_num, res);
-       }
        res->inflight_locks++;
-       mlog(0, "%s:%.*s: inflight++: now %u\n",
-            dlm->name, res->lockname.len, res->lockname.name,
-            res->inflight_locks);
+
+       mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name,
+            res->lockname.len, res->lockname.name, res->inflight_locks,
+            __builtin_return_address(0));
 }
 
-void __dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
-                                  struct dlm_lock_resource *res,
-                                  const char *file,
-                                  int line)
+void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
+                                  struct dlm_lock_resource *res)
 {
        assert_spin_locked(&res->spinlock);
 
        BUG_ON(res->inflight_locks == 0);
+
        res->inflight_locks--;
-       mlog(0, "%s:%.*s: inflight--: now %u\n",
-            dlm->name, res->lockname.len, res->lockname.name,
-            res->inflight_locks);
-       if (res->inflight_locks == 0)
-               dlm_lockres_clear_refmap_bit(dlm->node_num, res);
+
+       mlog(0, "%s: res %.*s, inflight--: now %u, %ps()\n", dlm->name,
+            res->lockname.len, res->lockname.name, res->inflight_locks,
+            __builtin_return_address(0));
+
        wake_up(&res->wq);
 }
 
@@ -697,7 +712,6 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
        unsigned int hash;
        int tries = 0;
        int bit, wait_on_recovery = 0;
-       int drop_inflight_if_nonlocal = 0;
 
        BUG_ON(!lockid);
 
@@ -709,36 +723,33 @@ lookup:
        spin_lock(&dlm->spinlock);
        tmpres = __dlm_lookup_lockres_full(dlm, lockid, namelen, hash);
        if (tmpres) {
-               int dropping_ref = 0;
-
                spin_unlock(&dlm->spinlock);
-
                spin_lock(&tmpres->spinlock);
-               /* We wait for the other thread that is mastering the resource */
+               /* Wait on the thread that is mastering the resource */
                if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
                        __dlm_wait_on_lockres(tmpres);
                        BUG_ON(tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN);
+                       spin_unlock(&tmpres->spinlock);
+                       dlm_lockres_put(tmpres);
+                       tmpres = NULL;
+                       goto lookup;
                }
 
-               if (tmpres->owner == dlm->node_num) {
-                       BUG_ON(tmpres->state & DLM_LOCK_RES_DROPPING_REF);
-                       dlm_lockres_grab_inflight_ref(dlm, tmpres);
-               } else if (tmpres->state & DLM_LOCK_RES_DROPPING_REF)
-                       dropping_ref = 1;
-               spin_unlock(&tmpres->spinlock);
-
-               /* wait until done messaging the master, drop our ref to allow
-                * the lockres to be purged, start over. */
-               if (dropping_ref) {
-                       spin_lock(&tmpres->spinlock);
-                       __dlm_wait_on_lockres_flags(tmpres, DLM_LOCK_RES_DROPPING_REF);
+               /* Wait on the resource purge to complete before continuing */
+               if (tmpres->state & DLM_LOCK_RES_DROPPING_REF) {
+                       BUG_ON(tmpres->owner == dlm->node_num);
+                       __dlm_wait_on_lockres_flags(tmpres,
+                                                   DLM_LOCK_RES_DROPPING_REF);
                        spin_unlock(&tmpres->spinlock);
                        dlm_lockres_put(tmpres);
                        tmpres = NULL;
                        goto lookup;
                }
 
-               mlog(0, "found in hash!\n");
+               /* Grab inflight ref to pin the resource */
+               dlm_lockres_grab_inflight_ref(dlm, tmpres);
+
+               spin_unlock(&tmpres->spinlock);
                if (res)
                        dlm_lockres_put(res);
                res = tmpres;
@@ -829,8 +840,8 @@ lookup:
                 * but they might own this lockres.  wait on them. */
                bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0);
                if (bit < O2NM_MAX_NODES) {
-                       mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to "
-                            "recover before lock mastery can begin\n",
+                       mlog(0, "%s: res %.*s, At least one node (%d) "
+                            "to recover before lock mastery can begin\n",
                             dlm->name, namelen, (char *)lockid, bit);
                        wait_on_recovery = 1;
                }
@@ -843,12 +854,11 @@ lookup:
 
        /* finally add the lockres to its hash bucket */
        __dlm_insert_lockres(dlm, res);
-       /* since this lockres is new it doesn't not require the spinlock */
-       dlm_lockres_grab_inflight_ref_new(dlm, res);
 
-       /* if this node does not become the master make sure to drop
-        * this inflight reference below */
-       drop_inflight_if_nonlocal = 1;
+       /* Grab inflight ref to pin the resource */
+       spin_lock(&res->spinlock);
+       dlm_lockres_grab_inflight_ref(dlm, res);
+       spin_unlock(&res->spinlock);
 
        /* get an extra ref on the mle in case this is a BLOCK
         * if so, the creator of the BLOCK may try to put the last
@@ -864,8 +874,8 @@ redo_request:
                 * dlm spinlock would be detectable be a change on the mle,
                 * so we only need to clear out the recovery map once. */
                if (dlm_is_recovery_lock(lockid, namelen)) {
-                       mlog(ML_NOTICE, "%s: recovery map is not empty, but "
-                            "must master $RECOVERY lock now\n", dlm->name);
+                       mlog(0, "%s: Recovery map is not empty, but must "
+                            "master $RECOVERY lock now\n", dlm->name);
                        if (!dlm_pre_master_reco_lockres(dlm, res))
                                wait_on_recovery = 0;
                        else {
@@ -883,8 +893,8 @@ redo_request:
                spin_lock(&dlm->spinlock);
                bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0);
                if (bit < O2NM_MAX_NODES) {
-                       mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to "
-                            "recover before lock mastery can begin\n",
+                       mlog(0, "%s: res %.*s, At least one node (%d) "
+                            "to recover before lock mastery can begin\n",
                             dlm->name, namelen, (char *)lockid, bit);
                        wait_on_recovery = 1;
                } else
@@ -913,8 +923,8 @@ redo_request:
                         * yet, keep going until it does.  this is how the
                         * master will know that asserts are needed back to
                         * the lower nodes. */
-                       mlog(0, "%s:%.*s: requests only up to %u but master "
-                            "is %u, keep going\n", dlm->name, namelen,
+                       mlog(0, "%s: res %.*s, Requests only up to %u but "
+                            "master is %u, keep going\n", dlm->name, namelen,
                             lockid, nodenum, mle->master);
                }
        }
@@ -924,13 +934,12 @@ wait:
        ret = dlm_wait_for_lock_mastery(dlm, res, mle, &blocked);
        if (ret < 0) {
                wait_on_recovery = 1;
-               mlog(0, "%s:%.*s: node map changed, redo the "
-                    "master request now, blocked=%d\n",
-                    dlm->name, res->lockname.len,
+               mlog(0, "%s: res %.*s, Node map changed, redo the master "
+                    "request now, blocked=%d\n", dlm->name, res->lockname.len,
                     res->lockname.name, blocked);
                if (++tries > 20) {
-                       mlog(ML_ERROR, "%s:%.*s: spinning on "
-                            "dlm_wait_for_lock_mastery, blocked=%d\n",
+                       mlog(ML_ERROR, "%s: res %.*s, Spinning on "
+                            "dlm_wait_for_lock_mastery, blocked = %d\n",
                             dlm->name, res->lockname.len,
                             res->lockname.name, blocked);
                        dlm_print_one_lock_resource(res);
@@ -940,7 +949,8 @@ wait:
                goto redo_request;
        }
 
-       mlog(0, "lockres mastered by %u\n", res->owner);
+       mlog(0, "%s: res %.*s, Mastered by %u\n", dlm->name, res->lockname.len,
+            res->lockname.name, res->owner);
        /* make sure we never continue without this */
        BUG_ON(res->owner == O2NM_MAX_NODES);
 
@@ -952,8 +962,6 @@ wait:
 
 wake_waiters:
        spin_lock(&res->spinlock);
-       if (res->owner != dlm->node_num && drop_inflight_if_nonlocal)
-               dlm_lockres_drop_inflight_ref(dlm, res);
        res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
        spin_unlock(&res->spinlock);
        wake_up(&res->wq);
@@ -1426,9 +1434,7 @@ way_up_top:
                }
 
                if (res->owner == dlm->node_num) {
-                       mlog(0, "%s:%.*s: setting bit %u in refmap\n",
-                            dlm->name, namelen, name, request->node_idx);
-                       dlm_lockres_set_refmap_bit(request->node_idx, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, request->node_idx);
                        spin_unlock(&res->spinlock);
                        response = DLM_MASTER_RESP_YES;
                        if (mle)
@@ -1493,10 +1499,8 @@ way_up_top:
                                 * go back and clean the mles on any
                                 * other nodes */
                                dispatch_assert = 1;
-                               dlm_lockres_set_refmap_bit(request->node_idx, res);
-                               mlog(0, "%s:%.*s: setting bit %u in refmap\n",
-                                    dlm->name, namelen, name,
-                                    request->node_idx);
+                               dlm_lockres_set_refmap_bit(dlm, res,
+                                                          request->node_idx);
                        } else
                                response = DLM_MASTER_RESP_NO;
                } else {
@@ -1702,7 +1706,7 @@ again:
                             "lockres, set the bit in the refmap\n",
                             namelen, lockname, to);
                        spin_lock(&res->spinlock);
-                       dlm_lockres_set_refmap_bit(to, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, to);
                        spin_unlock(&res->spinlock);
                }
        }
@@ -2187,8 +2191,6 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
        namelen = res->lockname.len;
        BUG_ON(namelen > O2NM_MAX_NAME_LEN);
 
-       mlog(0, "%s:%.*s: sending deref to %d\n",
-            dlm->name, namelen, lockname, res->owner);
        memset(&deref, 0, sizeof(deref));
        deref.node_idx = dlm->node_num;
        deref.namelen = namelen;
@@ -2197,14 +2199,12 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
        ret = o2net_send_message(DLM_DEREF_LOCKRES_MSG, dlm->key,
                                 &deref, sizeof(deref), res->owner, &r);
        if (ret < 0)
-               mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to "
-                    "node %u\n", ret, DLM_DEREF_LOCKRES_MSG, dlm->key,
-                    res->owner);
+               mlog(ML_ERROR, "%s: res %.*s, error %d send DEREF to node %u\n",
+                    dlm->name, namelen, lockname, ret, res->owner);
        else if (r < 0) {
                /* BAD.  other node says I did not have a ref. */
-               mlog(ML_ERROR,"while dropping ref on %s:%.*s "
-                   "(master=%u) got %d.\n", dlm->name, namelen,
-                   lockname, res->owner, r);
+               mlog(ML_ERROR, "%s: res %.*s, DEREF to node %u got %d\n",
+                    dlm->name, namelen, lockname, res->owner, r);
                dlm_print_one_lock_resource(res);
                BUG();
        }
@@ -2260,7 +2260,7 @@ int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
        else {
                BUG_ON(res->state & DLM_LOCK_RES_DROPPING_REF);
                if (test_bit(node, res->refmap)) {
-                       dlm_lockres_clear_refmap_bit(node, res);
+                       dlm_lockres_clear_refmap_bit(dlm, res, node);
                        cleared = 1;
                }
        }
@@ -2320,7 +2320,7 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
        BUG_ON(res->state & DLM_LOCK_RES_DROPPING_REF);
        if (test_bit(node, res->refmap)) {
                __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
-               dlm_lockres_clear_refmap_bit(node, res);
+               dlm_lockres_clear_refmap_bit(dlm, res, node);
                cleared = 1;
        }
        spin_unlock(&res->spinlock);
@@ -2802,7 +2802,8 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
                                BUG_ON(!list_empty(&lock->bast_list));
                                BUG_ON(lock->ast_pending);
                                BUG_ON(lock->bast_pending);
-                               dlm_lockres_clear_refmap_bit(lock->ml.node, res);
+                               dlm_lockres_clear_refmap_bit(dlm, res,
+                                                            lock->ml.node);
                                list_del_init(&lock->list);
                                dlm_lock_put(lock);
                                /* In a normal unlock, we would have added a
@@ -2823,7 +2824,7 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
                        mlog(0, "%s:%.*s: node %u had a ref to this "
                             "migrating lockres, clearing\n", dlm->name,
                             res->lockname.len, res->lockname.name, bit);
-                       dlm_lockres_clear_refmap_bit(bit, res);
+                       dlm_lockres_clear_refmap_bit(dlm, res, bit);
                }
                bit++;
        }
@@ -2916,9 +2917,9 @@ static int dlm_do_migrate_request(struct dlm_ctxt *dlm,
                                         &migrate, sizeof(migrate), nodenum,
                                         &status);
                if (ret < 0) {
-                       mlog(ML_ERROR, "Error %d when sending message %u (key "
-                            "0x%x) to node %u\n", ret, DLM_MIGRATE_REQUEST_MSG,
-                            dlm->key, nodenum);
+                       mlog(ML_ERROR, "%s: res %.*s, Error %d send "
+                            "MIGRATE_REQUEST to node %u\n", dlm->name,
+                            migrate.namelen, migrate.name, ret, nodenum);
                        if (!dlm_is_host_down(ret)) {
                                mlog(ML_ERROR, "unhandled error=%d!\n", ret);
                                BUG();
@@ -2937,7 +2938,7 @@ static int dlm_do_migrate_request(struct dlm_ctxt *dlm,
                             dlm->name, res->lockname.len, res->lockname.name,
                             nodenum);
                        spin_lock(&res->spinlock);
-                       dlm_lockres_set_refmap_bit(nodenum, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, nodenum);
                        spin_unlock(&res->spinlock);
                }
        }
@@ -3271,7 +3272,7 @@ int dlm_finish_migration(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
         * mastery reference here since old_master will briefly have
         * a reference after the migration completes */
        spin_lock(&res->spinlock);
-       dlm_lockres_set_refmap_bit(old_master, res);
+       dlm_lockres_set_refmap_bit(dlm, res, old_master);
        spin_unlock(&res->spinlock);
 
        mlog(0, "now time to do a migrate request to other nodes\n");
index 7efab6d28a21b4ee6a8376559d70f739a4e1da90..01ebfd0bdad72264b99345378f0c6febe246503d 100644 (file)
@@ -362,40 +362,38 @@ static int dlm_is_node_recovered(struct dlm_ctxt *dlm, u8 node)
 }
 
 
-int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout)
+void dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout)
 {
-       if (timeout) {
-               mlog(ML_NOTICE, "%s: waiting %dms for notification of "
-                    "death of node %u\n", dlm->name, timeout, node);
+       if (dlm_is_node_dead(dlm, node))
+               return;
+
+       printk(KERN_NOTICE "o2dlm: Waiting on the death of node %u in "
+              "domain %s\n", node, dlm->name);
+
+       if (timeout)
                wait_event_timeout(dlm->dlm_reco_thread_wq,
-                          dlm_is_node_dead(dlm, node),
-                          msecs_to_jiffies(timeout));
-       } else {
-               mlog(ML_NOTICE, "%s: waiting indefinitely for notification "
-                    "of death of node %u\n", dlm->name, node);
+                                  dlm_is_node_dead(dlm, node),
+                                  msecs_to_jiffies(timeout));
+       else
                wait_event(dlm->dlm_reco_thread_wq,
                           dlm_is_node_dead(dlm, node));
-       }
-       /* for now, return 0 */
-       return 0;
 }
 
-int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout)
+void dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout)
 {
-       if (timeout) {
-               mlog(0, "%s: waiting %dms for notification of "
-                    "recovery of node %u\n", dlm->name, timeout, node);
+       if (dlm_is_node_recovered(dlm, node))
+               return;
+
+       printk(KERN_NOTICE "o2dlm: Waiting on the recovery of node %u in "
+              "domain %s\n", node, dlm->name);
+
+       if (timeout)
                wait_event_timeout(dlm->dlm_reco_thread_wq,
-                          dlm_is_node_recovered(dlm, node),
-                          msecs_to_jiffies(timeout));
-       } else {
-               mlog(0, "%s: waiting indefinitely for notification "
-                    "of recovery of node %u\n", dlm->name, node);
+                                  dlm_is_node_recovered(dlm, node),
+                                  msecs_to_jiffies(timeout));
+       else
                wait_event(dlm->dlm_reco_thread_wq,
                           dlm_is_node_recovered(dlm, node));
-       }
-       /* for now, return 0 */
-       return 0;
 }
 
 /* callers of the top-level api calls (dlmlock/dlmunlock) should
@@ -430,6 +428,8 @@ static void dlm_begin_recovery(struct dlm_ctxt *dlm)
 {
        spin_lock(&dlm->spinlock);
        BUG_ON(dlm->reco.state & DLM_RECO_STATE_ACTIVE);
+       printk(KERN_NOTICE "o2dlm: Begin recovery on domain %s for node %u\n",
+              dlm->name, dlm->reco.dead_node);
        dlm->reco.state |= DLM_RECO_STATE_ACTIVE;
        spin_unlock(&dlm->spinlock);
 }
@@ -440,9 +440,18 @@ static void dlm_end_recovery(struct dlm_ctxt *dlm)
        BUG_ON(!(dlm->reco.state & DLM_RECO_STATE_ACTIVE));
        dlm->reco.state &= ~DLM_RECO_STATE_ACTIVE;
        spin_unlock(&dlm->spinlock);
+       printk(KERN_NOTICE "o2dlm: End recovery on domain %s\n", dlm->name);
        wake_up(&dlm->reco.event);
 }
 
+static void dlm_print_recovery_master(struct dlm_ctxt *dlm)
+{
+       printk(KERN_NOTICE "o2dlm: Node %u (%s) is the Recovery Master for the "
+              "dead node %u in domain %s\n", dlm->reco.new_master,
+              (dlm->node_num == dlm->reco.new_master ? "me" : "he"),
+              dlm->reco.dead_node, dlm->name);
+}
+
 static int dlm_do_recovery(struct dlm_ctxt *dlm)
 {
        int status = 0;
@@ -505,9 +514,8 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
                }
                mlog(0, "another node will master this recovery session.\n");
        }
-       mlog(0, "dlm=%s (%d), new_master=%u, this node=%u, dead_node=%u\n",
-            dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), dlm->reco.new_master,
-            dlm->node_num, dlm->reco.dead_node);
+
+       dlm_print_recovery_master(dlm);
 
        /* it is safe to start everything back up here
         * because all of the dead node's lock resources
@@ -518,15 +526,13 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
        return 0;
 
 master_here:
-       mlog(ML_NOTICE, "(%d) Node %u is the Recovery Master for the Dead Node "
-            "%u for Domain %s\n", task_pid_nr(dlm->dlm_reco_thread_task),
-            dlm->node_num, dlm->reco.dead_node, dlm->name);
+       dlm_print_recovery_master(dlm);
 
        status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
        if (status < 0) {
                /* we should never hit this anymore */
-               mlog(ML_ERROR, "error %d remastering locks for node %u, "
-                    "retrying.\n", status, dlm->reco.dead_node);
+               mlog(ML_ERROR, "%s: Error %d remastering locks for node %u, "
+                    "retrying.\n", dlm->name, status, dlm->reco.dead_node);
                /* yield a bit to allow any final network messages
                 * to get handled on remaining nodes */
                msleep(100);
@@ -567,7 +573,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
                BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT);
                ndata->state = DLM_RECO_NODE_DATA_REQUESTING;
 
-               mlog(0, "requesting lock info from node %u\n",
+               mlog(0, "%s: Requesting lock info from node %u\n", dlm->name,
                     ndata->node_num);
 
                if (ndata->node_num == dlm->node_num) {
@@ -640,7 +646,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
                spin_unlock(&dlm_reco_state_lock);
        }
 
-       mlog(0, "done requesting all lock info\n");
+       mlog(0, "%s: Done requesting all lock info\n", dlm->name);
 
        /* nodes should be sending reco data now
         * just need to wait */
@@ -802,10 +808,9 @@ static int dlm_request_all_locks(struct dlm_ctxt *dlm, u8 request_from,
 
        /* negative status is handled by caller */
        if (ret < 0)
-               mlog(ML_ERROR, "Error %d when sending message %u (key "
-                    "0x%x) to node %u\n", ret, DLM_LOCK_REQUEST_MSG,
-                    dlm->key, request_from);
-
+               mlog(ML_ERROR, "%s: Error %d send LOCK_REQUEST to node %u "
+                    "to recover dead node %u\n", dlm->name, ret,
+                    request_from, dead_node);
        // return from here, then
        // sleep until all received or error
        return ret;
@@ -956,9 +961,9 @@ static int dlm_send_all_done_msg(struct dlm_ctxt *dlm, u8 dead_node, u8 send_to)
        ret = o2net_send_message(DLM_RECO_DATA_DONE_MSG, dlm->key, &done_msg,
                                 sizeof(done_msg), send_to, &tmpret);
        if (ret < 0) {
-               mlog(ML_ERROR, "Error %d when sending message %u (key "
-                    "0x%x) to node %u\n", ret, DLM_RECO_DATA_DONE_MSG,
-                    dlm->key, send_to);
+               mlog(ML_ERROR, "%s: Error %d send RECO_DATA_DONE to node %u "
+                    "to recover dead node %u\n", dlm->name, ret, send_to,
+                    dead_node);
                if (!dlm_is_host_down(ret)) {
                        BUG();
                }
@@ -1127,9 +1132,11 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
        if (ret < 0) {
                /* XXX: negative status is not handled.
                 * this will end up killing this node. */
-               mlog(ML_ERROR, "Error %d when sending message %u (key "
-                    "0x%x) to node %u\n", ret, DLM_MIG_LOCKRES_MSG,
-                    dlm->key, send_to);
+               mlog(ML_ERROR, "%s: res %.*s, Error %d send MIG_LOCKRES to "
+                    "node %u (%s)\n", dlm->name, mres->lockname_len,
+                    mres->lockname, ret, send_to,
+                    (orig_flags & DLM_MRES_MIGRATION ?
+                     "migration" : "recovery"));
        } else {
                /* might get an -ENOMEM back here */
                ret = status;
@@ -1767,7 +1774,7 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
                             dlm->name, mres->lockname_len, mres->lockname,
                             from);
                        spin_lock(&res->spinlock);
-                       dlm_lockres_set_refmap_bit(from, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, from);
                        spin_unlock(&res->spinlock);
                        added++;
                        break;
@@ -1965,7 +1972,7 @@ skip_lvb:
                        mlog(0, "%s:%.*s: added lock for node %u, "
                             "setting refmap bit\n", dlm->name,
                             res->lockname.len, res->lockname.name, ml->node);
-                       dlm_lockres_set_refmap_bit(ml->node, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, ml->node);
                        added++;
                }
                spin_unlock(&res->spinlock);
@@ -2084,6 +2091,9 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
 
        list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
                if (res->owner == dead_node) {
+                       mlog(0, "%s: res %.*s, Changing owner from %u to %u\n",
+                            dlm->name, res->lockname.len, res->lockname.name,
+                            res->owner, new_master);
                        list_del_init(&res->recovering);
                        spin_lock(&res->spinlock);
                        /* new_master has our reference from
@@ -2105,40 +2115,30 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
        for (i = 0; i < DLM_HASH_BUCKETS; i++) {
                bucket = dlm_lockres_hash(dlm, i);
                hlist_for_each_entry(res, hash_iter, bucket, hash_node) {
-                       if (res->state & DLM_LOCK_RES_RECOVERING) {
-                               if (res->owner == dead_node) {
-                                       mlog(0, "(this=%u) res %.*s owner=%u "
-                                            "was not on recovering list, but "
-                                            "clearing state anyway\n",
-                                            dlm->node_num, res->lockname.len,
-                                            res->lockname.name, new_master);
-                               } else if (res->owner == dlm->node_num) {
-                                       mlog(0, "(this=%u) res %.*s owner=%u "
-                                            "was not on recovering list, "
-                                            "owner is THIS node, clearing\n",
-                                            dlm->node_num, res->lockname.len,
-                                            res->lockname.name, new_master);
-                               } else
-                                       continue;
+                       if (!(res->state & DLM_LOCK_RES_RECOVERING))
+                               continue;
 
-                               if (!list_empty(&res->recovering)) {
-                                       mlog(0, "%s:%.*s: lockres was "
-                                            "marked RECOVERING, owner=%u\n",
-                                            dlm->name, res->lockname.len,
-                                            res->lockname.name, res->owner);
-                                       list_del_init(&res->recovering);
-                                       dlm_lockres_put(res);
-                               }
-                               spin_lock(&res->spinlock);
-                               /* new_master has our reference from
-                                * the lock state sent during recovery */
-                               dlm_change_lockres_owner(dlm, res, new_master);
-                               res->state &= ~DLM_LOCK_RES_RECOVERING;
-                               if (__dlm_lockres_has_locks(res))
-                                       __dlm_dirty_lockres(dlm, res);
-                               spin_unlock(&res->spinlock);
-                               wake_up(&res->wq);
+                       if (res->owner != dead_node &&
+                           res->owner != dlm->node_num)
+                               continue;
+
+                       if (!list_empty(&res->recovering)) {
+                               list_del_init(&res->recovering);
+                               dlm_lockres_put(res);
                        }
+
+                       /* new_master has our reference from
+                        * the lock state sent during recovery */
+                       mlog(0, "%s: res %.*s, Changing owner from %u to %u\n",
+                            dlm->name, res->lockname.len, res->lockname.name,
+                            res->owner, new_master);
+                       spin_lock(&res->spinlock);
+                       dlm_change_lockres_owner(dlm, res, new_master);
+                       res->state &= ~DLM_LOCK_RES_RECOVERING;
+                       if (__dlm_lockres_has_locks(res))
+                               __dlm_dirty_lockres(dlm, res);
+                       spin_unlock(&res->spinlock);
+                       wake_up(&res->wq);
                }
        }
 }
@@ -2252,12 +2252,12 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
                             res->lockname.len, res->lockname.name, freed, dead_node);
                        __dlm_print_one_lock_resource(res);
                }
-               dlm_lockres_clear_refmap_bit(dead_node, res);
+               dlm_lockres_clear_refmap_bit(dlm, res, dead_node);
        } else if (test_bit(dead_node, res->refmap)) {
                mlog(0, "%s:%.*s: dead node %u had a ref, but had "
                     "no locks and had not purged before dying\n", dlm->name,
                     res->lockname.len, res->lockname.name, dead_node);
-               dlm_lockres_clear_refmap_bit(dead_node, res);
+               dlm_lockres_clear_refmap_bit(dlm, res, dead_node);
        }
 
        /* do not kick thread yet */
@@ -2324,9 +2324,9 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
                        dlm_revalidate_lvb(dlm, res, dead_node);
                        if (res->owner == dead_node) {
                                if (res->state & DLM_LOCK_RES_DROPPING_REF) {
-                                       mlog(ML_NOTICE, "Ignore %.*s for "
+                                       mlog(ML_NOTICE, "%s: res %.*s, Skip "
                                             "recovery as it is being freed\n",
-                                            res->lockname.len,
+                                            dlm->name, res->lockname.len,
                                             res->lockname.name);
                                } else
                                        dlm_move_lockres_to_recovery_list(dlm,
index 1d6d1d22c4715e3c89bef69570916cc5bf44c259..e73c833fc2a1a97cac35903f0439115cef813c69 100644 (file)
@@ -94,24 +94,26 @@ int __dlm_lockres_unused(struct dlm_lock_resource *res)
 {
        int bit;
 
+       assert_spin_locked(&res->spinlock);
+
        if (__dlm_lockres_has_locks(res))
                return 0;
 
+       /* Locks are in the process of being created */
+       if (res->inflight_locks)
+               return 0;
+
        if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY)
                return 0;
 
        if (res->state & DLM_LOCK_RES_RECOVERING)
                return 0;
 
+       /* Another node has this resource with this node as the master */
        bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
        if (bit < O2NM_MAX_NODES)
                return 0;
 
-       /*
-        * since the bit for dlm->node_num is not set, inflight_locks better
-        * be zero
-        */
-       BUG_ON(res->inflight_locks != 0);
        return 1;
 }
 
@@ -185,8 +187,6 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm,
                /* clear our bit from the master's refmap, ignore errors */
                ret = dlm_drop_lockres_ref(dlm, res);
                if (ret < 0) {
-                       mlog(ML_ERROR, "%s: deref %.*s failed %d\n", dlm->name,
-                            res->lockname.len, res->lockname.name, ret);
                        if (!dlm_is_host_down(ret))
                                BUG();
                }
@@ -209,7 +209,7 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm,
                BUG();
        }
 
-       __dlm_unhash_lockres(res);
+       __dlm_unhash_lockres(dlm, res);
 
        /* lockres is not in the hash now.  drop the flag and wake up
         * any processes waiting in dlm_get_lock_resource. */
index e1ed5e502ff25dc8afe39de464949ba13c2f9892..81a4cd22f80be84a06eac2b0fbf4348385d76262 100644 (file)
@@ -1692,7 +1692,7 @@ int ocfs2_open_lock(struct inode *inode)
        mlog(0, "inode %llu take PRMODE open lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-       if (ocfs2_mount_local(osb))
+       if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
                goto out;
 
        lockres = &OCFS2_I(inode)->ip_open_lockres;
@@ -1718,6 +1718,12 @@ int ocfs2_try_open_lock(struct inode *inode, int write)
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
 
+       if (ocfs2_is_hard_readonly(osb)) {
+               if (write)
+                       status = -EROFS;
+               goto out;
+       }
+
        if (ocfs2_mount_local(osb))
                goto out;
 
@@ -2298,7 +2304,7 @@ int ocfs2_inode_lock_full_nested(struct inode *inode,
        if (ocfs2_is_hard_readonly(osb)) {
                if (ex)
                        status = -EROFS;
-               goto bail;
+               goto getbh;
        }
 
        if (ocfs2_mount_local(osb))
@@ -2356,7 +2362,7 @@ local:
                        mlog_errno(status);
                goto bail;
        }
-
+getbh:
        if (ret_bh) {
                status = ocfs2_assign_bh(inode, ret_bh, local_bh);
                if (status < 0) {
@@ -2628,8 +2634,11 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex)
 
        BUG_ON(!dl);
 
-       if (ocfs2_is_hard_readonly(osb))
-               return -EROFS;
+       if (ocfs2_is_hard_readonly(osb)) {
+               if (ex)
+                       return -EROFS;
+               return 0;
+       }
 
        if (ocfs2_mount_local(osb))
                return 0;
@@ -2647,7 +2656,7 @@ void ocfs2_dentry_unlock(struct dentry *dentry, int ex)
        struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
        struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
-       if (!ocfs2_mount_local(osb))
+       if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
                ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
 }
 
index 23457b491e8ce53ac5b71d9cd5fc2a5e1400a07f..2f5b92ef0e533146007b49d21dd705a242125dc5 100644 (file)
@@ -832,6 +832,102 @@ out:
        return ret;
 }
 
+int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin)
+{
+       struct inode *inode = file->f_mapping->host;
+       int ret;
+       unsigned int is_last = 0, is_data = 0;
+       u16 cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+       u32 cpos, cend, clen, hole_size;
+       u64 extoff, extlen;
+       struct buffer_head *di_bh = NULL;
+       struct ocfs2_extent_rec rec;
+
+       BUG_ON(origin != SEEK_DATA && origin != SEEK_HOLE);
+
+       ret = ocfs2_inode_lock(inode, &di_bh, 0);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       down_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+       if (*offset >= inode->i_size) {
+               ret = -ENXIO;
+               goto out_unlock;
+       }
+
+       if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
+               if (origin == SEEK_HOLE)
+                       *offset = inode->i_size;
+               goto out_unlock;
+       }
+
+       clen = 0;
+       cpos = *offset >> cs_bits;
+       cend = ocfs2_clusters_for_bytes(inode->i_sb, inode->i_size);
+
+       while (cpos < cend && !is_last) {
+               ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos, &hole_size,
+                                                &rec, &is_last);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out_unlock;
+               }
+
+               extoff = cpos;
+               extoff <<= cs_bits;
+
+               if (rec.e_blkno == 0ULL) {
+                       clen = hole_size;
+                       is_data = 0;
+               } else {
+                       clen = le16_to_cpu(rec.e_leaf_clusters) -
+                               (cpos - le32_to_cpu(rec.e_cpos));
+                       is_data = (rec.e_flags & OCFS2_EXT_UNWRITTEN) ?  0 : 1;
+               }
+
+               if ((!is_data && origin == SEEK_HOLE) ||
+                   (is_data && origin == SEEK_DATA)) {
+                       if (extoff > *offset)
+                               *offset = extoff;
+                       goto out_unlock;
+               }
+
+               if (!is_last)
+                       cpos += clen;
+       }
+
+       if (origin == SEEK_HOLE) {
+               extoff = cpos;
+               extoff <<= cs_bits;
+               extlen = clen;
+               extlen <<=  cs_bits;
+
+               if ((extoff + extlen) > inode->i_size)
+                       extlen = inode->i_size - extoff;
+               extoff += extlen;
+               if (extoff > *offset)
+                       *offset = extoff;
+               goto out_unlock;
+       }
+
+       ret = -ENXIO;
+
+out_unlock:
+
+       brelse(di_bh);
+
+       up_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+       ocfs2_inode_unlock(inode, 0);
+out:
+       if (ret && ret != -ENXIO)
+               ret = -ENXIO;
+       return ret;
+}
+
 int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
                           struct buffer_head *bhs[], int flags,
                           int (*validate)(struct super_block *sb,
index e79d41c2c90972fe801a99ec040b229a92debe98..67ea57d2fd594da7e456c1103bb1652fa68b5f69 100644 (file)
@@ -53,6 +53,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
 int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                 u64 map_start, u64 map_len);
 
+int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin);
+
 int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
                             u32 *p_cluster, u32 *num_clusters,
                             struct ocfs2_extent_list *el,
index de4ea1af041b654f8f1b4f1a000f6492226f701f..6e396683c3d48af7321f77b8658754982586cb35 100644 (file)
@@ -1950,6 +1950,9 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
        if (ret < 0)
                mlog_errno(ret);
 
+       if (file->f_flags & O_SYNC)
+               handle->h_sync = 1;
+
        ocfs2_commit_trans(osb, handle);
 
 out_inode_unlock:
@@ -2052,6 +2055,23 @@ out:
        return ret;
 }
 
+static void ocfs2_aiodio_wait(struct inode *inode)
+{
+       wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
+
+       wait_event(*wq, (atomic_read(&OCFS2_I(inode)->ip_unaligned_aio) == 0));
+}
+
+static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)
+{
+       int blockmask = inode->i_sb->s_blocksize - 1;
+       loff_t final_size = pos + count;
+
+       if ((pos & blockmask) || (final_size & blockmask))
+               return 1;
+       return 0;
+}
+
 static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
                                            struct file *file,
                                            loff_t pos, size_t count,
@@ -2230,6 +2250,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        int full_coherency = !(osb->s_mount_opt &
                               OCFS2_MOUNT_COHERENCY_BUFFERED);
+       int unaligned_dio = 0;
 
        trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
                (unsigned long long)OCFS2_I(inode)->ip_blkno,
@@ -2297,6 +2318,10 @@ relock:
                goto out;
        }
 
+       if (direct_io && !is_sync_kiocb(iocb))
+               unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_left,
+                                                     *ppos);
+
        /*
         * We can't complete the direct I/O as requested, fall back to
         * buffered I/O.
@@ -2311,6 +2336,18 @@ relock:
                goto relock;
        }
 
+       if (unaligned_dio) {
+               /*
+                * Wait on previous unaligned aio to complete before
+                * proceeding.
+                */
+               ocfs2_aiodio_wait(inode);
+
+               /* Mark the iocb as needing a decrement in ocfs2_dio_end_io */
+               atomic_inc(&OCFS2_I(inode)->ip_unaligned_aio);
+               ocfs2_iocb_set_unaligned_aio(iocb);
+       }
+
        /*
         * To later detect whether a journal commit for sync writes is
         * necessary, we sample i_size, and cluster count here.
@@ -2382,8 +2419,12 @@ out_dio:
        if ((ret == -EIOCBQUEUED) || (!ocfs2_iocb_is_rw_locked(iocb))) {
                rw_level = -1;
                have_alloc_sem = 0;
+               unaligned_dio = 0;
        }
 
+       if (unaligned_dio)
+               atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio);
+
 out:
        if (rw_level != -1)
                ocfs2_rw_unlock(inode, rw_level);
@@ -2591,6 +2632,57 @@ bail:
        return ret;
 }
 
+/* Refer generic_file_llseek_unlocked() */
+static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int origin)
+{
+       struct inode *inode = file->f_mapping->host;
+       int ret = 0;
+
+       mutex_lock(&inode->i_mutex);
+
+       switch (origin) {
+       case SEEK_SET:
+               break;
+       case SEEK_END:
+               offset += inode->i_size;
+               break;
+       case SEEK_CUR:
+               if (offset == 0) {
+                       offset = file->f_pos;
+                       goto out;
+               }
+               offset += file->f_pos;
+               break;
+       case SEEK_DATA:
+       case SEEK_HOLE:
+               ret = ocfs2_seek_data_hole_offset(file, &offset, origin);
+               if (ret)
+                       goto out;
+               break;
+       default:
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
+               ret = -EINVAL;
+       if (!ret && offset > inode->i_sb->s_maxbytes)
+               ret = -EINVAL;
+       if (ret)
+               goto out;
+
+       if (offset != file->f_pos) {
+               file->f_pos = offset;
+               file->f_version = 0;
+       }
+
+out:
+       mutex_unlock(&inode->i_mutex);
+       if (ret)
+               return ret;
+       return offset;
+}
+
 const struct inode_operations ocfs2_file_iops = {
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
@@ -2615,7 +2707,7 @@ const struct inode_operations ocfs2_special_file_iops = {
  * ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
  */
 const struct file_operations ocfs2_fops = {
-       .llseek         = generic_file_llseek,
+       .llseek         = ocfs2_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
        .mmap           = ocfs2_mmap,
@@ -2663,7 +2755,7 @@ const struct file_operations ocfs2_dops = {
  * the cluster.
  */
 const struct file_operations ocfs2_fops_no_plocks = {
-       .llseek         = generic_file_llseek,
+       .llseek         = ocfs2_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
        .mmap           = ocfs2_mmap,
index a22d2c098890a9ca67e2056976bfc9869d74a325..17454a904d7bf488093de9f3db61dc529e0f8e3c 100644 (file)
@@ -951,7 +951,7 @@ static void ocfs2_cleanup_delete_inode(struct inode *inode,
        trace_ocfs2_cleanup_delete_inode(
                (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data);
        if (sync_data)
-               write_inode_now(inode, 1);
+               filemap_write_and_wait(inode->i_mapping);
        truncate_inode_pages(&inode->i_data, 0);
 }
 
index 1c508b149b3ac1bd4325fd33a9aae6bdb70e024a..88924a3133fae7c15ca3f5a5259b64eecd97022e 100644 (file)
@@ -43,6 +43,9 @@ struct ocfs2_inode_info
        /* protects extended attribute changes on this inode */
        struct rw_semaphore             ip_xattr_sem;
 
+       /* Number of outstanding AIO's which are not page aligned */
+       atomic_t                        ip_unaligned_aio;
+
        /* These fields are protected by ip_lock */
        spinlock_t                      ip_lock;
        u32                             ip_open_count;
index bc91072b72196fd335c4b7cbc02ba08cb67254e6..726ff265b296bc3365cfe46e94588c1ee4f6ed6a 100644 (file)
@@ -122,7 +122,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
        if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
                (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
                if (!capable(CAP_LINUX_IMMUTABLE))
-                       goto bail_unlock;
+                       goto bail_commit;
        }
 
        ocfs2_inode->ip_attr = flags;
@@ -132,6 +132,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
        if (status < 0)
                mlog_errno(status);
 
+bail_commit:
        ocfs2_commit_trans(osb, handle);
 bail_unlock:
        ocfs2_inode_unlock(inode, 1);
@@ -381,7 +382,7 @@ int ocfs2_info_handle_freeinode(struct inode *inode,
        if (!oifi) {
                status = -ENOMEM;
                mlog_errno(status);
-               goto bail;
+               goto out_err;
        }
 
        if (o2info_from_user(*oifi, req))
@@ -431,7 +432,7 @@ bail:
                o2info_set_request_error(&oifi->ifi_req, req);
 
        kfree(oifi);
-
+out_err:
        return status;
 }
 
@@ -666,7 +667,7 @@ int ocfs2_info_handle_freefrag(struct inode *inode,
        if (!oiff) {
                status = -ENOMEM;
                mlog_errno(status);
-               goto bail;
+               goto out_err;
        }
 
        if (o2info_from_user(*oiff, req))
@@ -716,7 +717,7 @@ bail:
                o2info_set_request_error(&oiff->iff_req, req);
 
        kfree(oiff);
-
+out_err:
        return status;
 }
 
index 295d56454e8b23b6e9d97a6bd258e6170311c8f5..0a42ae96dca7d4a0f662505e0e51206895ce4156 100644 (file)
@@ -1544,9 +1544,9 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
        /* we need to run complete recovery for offline orphan slots */
        ocfs2_replay_map_set_state(osb, REPLAY_NEEDED);
 
-       mlog(ML_NOTICE, "Recovering node %d from slot %d on device (%u,%u)\n",
-            node_num, slot_num,
-            MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+       printk(KERN_NOTICE "ocfs2: Begin replay journal (node %d, slot %d) on "\
+              "device (%u,%u)\n", node_num, slot_num, MAJOR(osb->sb->s_dev),
+              MINOR(osb->sb->s_dev));
 
        OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
 
@@ -1601,6 +1601,9 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
 
        jbd2_journal_destroy(journal);
 
+       printk(KERN_NOTICE "ocfs2: End replay journal (node %d, slot %d) on "\
+              "device (%u,%u)\n", node_num, slot_num, MAJOR(osb->sb->s_dev),
+              MINOR(osb->sb->s_dev));
 done:
        /* drop the lock on this nodes journal */
        if (got_lock)
@@ -1808,6 +1811,20 @@ static inline unsigned long ocfs2_orphan_scan_timeout(void)
  * every slot, queuing a recovery of the slot on the ocfs2_wq thread. This
  * is done to catch any orphans that are left over in orphan directories.
  *
+ * It scans all slots, even ones that are in use. It does so to handle the
+ * case described below:
+ *
+ *   Node 1 has an inode it was using. The dentry went away due to memory
+ *   pressure.  Node 1 closes the inode, but it's on the free list. The node
+ *   has the open lock.
+ *   Node 2 unlinks the inode. It grabs the dentry lock to notify others,
+ *   but node 1 has no dentry and doesn't get the message. It trylocks the
+ *   open lock, sees that another node has a PR, and does nothing.
+ *   Later node 2 runs its orphan dir. It igets the inode, trylocks the
+ *   open lock, sees the PR still, and does nothing.
+ *   Basically, we have to trigger an orphan iput on node 1. The only way
+ *   for this to happen is if node 1 runs node 2's orphan dir.
+ *
  * ocfs2_queue_orphan_scan gets called every ORPHAN_SCAN_SCHEDULE_TIMEOUT
  * seconds.  It gets an EX lock on os_lockres and checks sequence number
  * stored in LVB. If the sequence number has changed, it means some other
index 68cf2f6d3c6a40b22dda3e2d4f7e2d44349167fa..a3385b63ff5e542bcfaabe59744fa3af38b537e4 100644 (file)
@@ -441,10 +441,11 @@ static inline int ocfs2_mknod_credits(struct super_block *sb, int is_dir,
 #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
 
 /* file update (nlink, etc) + directory mtime/ctime + dir entry block + quota
- * update on dir + index leaf + dx root update for free list */
+ * update on dir + index leaf + dx root update for free list +
+ * previous dirblock update in the free list */
 static inline int ocfs2_link_credits(struct super_block *sb)
 {
-       return 2*OCFS2_INODE_UPDATE_CREDITS + 3 +
+       return 2*OCFS2_INODE_UPDATE_CREDITS + 4 +
               ocfs2_quota_trans_credits(sb);
 }
 
index 3e9393ca39ebd823772ae910cda1b4516d46fa62..9cd41083e99123eca1c48085fb39809e6b906b40 100644 (file)
@@ -61,7 +61,7 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
 static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
                                struct page *page)
 {
-       int ret;
+       int ret = VM_FAULT_NOPAGE;
        struct inode *inode = file->f_path.dentry->d_inode;
        struct address_space *mapping = inode->i_mapping;
        loff_t pos = page_offset(page);
@@ -71,32 +71,25 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
        void *fsdata;
        loff_t size = i_size_read(inode);
 
-       /*
-        * Another node might have truncated while we were waiting on
-        * cluster locks.
-        * We don't check size == 0 before the shift. This is borrowed
-        * from do_generic_file_read.
-        */
        last_index = (size - 1) >> PAGE_CACHE_SHIFT;
-       if (unlikely(!size || page->index > last_index)) {
-               ret = -EINVAL;
-               goto out;
-       }
 
        /*
-        * The i_size check above doesn't catch the case where nodes
-        * truncated and then re-extended the file. We'll re-check the
-        * page mapping after taking the page lock inside of
-        * ocfs2_write_begin_nolock().
+        * There are cases that lead to the page no longer bebongs to the
+        * mapping.
+        * 1) pagecache truncates locally due to memory pressure.
+        * 2) pagecache truncates when another is taking EX lock against 
+        * inode lock. see ocfs2_data_convert_worker.
+        * 
+        * The i_size check doesn't catch the case where nodes truncated and
+        * then re-extended the file. We'll re-check the page mapping after
+        * taking the page lock inside of ocfs2_write_begin_nolock().
+        *
+        * Let VM retry with these cases.
         */
-       if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
-               /*
-                * the page has been umapped in ocfs2_data_downconvert_worker.
-                * So return 0 here and let VFS retry.
-                */
-               ret = 0;
+       if ((page->mapping != inode->i_mapping) ||
+           (!PageUptodate(page)) ||
+           (page_offset(page) >= size))
                goto out;
-       }
 
        /*
         * Call ocfs2_write_begin() and ocfs2_write_end() to take
@@ -116,17 +109,21 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
        if (ret) {
                if (ret != -ENOSPC)
                        mlog_errno(ret);
+               if (ret == -ENOMEM)
+                       ret = VM_FAULT_OOM;
+               else
+                       ret = VM_FAULT_SIGBUS;
                goto out;
        }
 
-       ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
-                                    fsdata);
-       if (ret < 0) {
-               mlog_errno(ret);
+       if (!locked_page) {
+               ret = VM_FAULT_NOPAGE;
                goto out;
        }
+       ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
+                                    fsdata);
        BUG_ON(ret != len);
-       ret = 0;
+       ret = VM_FAULT_LOCKED;
 out:
        return ret;
 }
@@ -168,8 +165,6 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 out:
        ocfs2_unblock_signals(&oldset);
-       if (ret)
-               ret = VM_FAULT_SIGBUS;
        return ret;
 }
 
index d53cb706f14c27dfc5ec754dc6d0f846e424421c..184c76b8c293907368f325316da04f57801d87eb 100644 (file)
@@ -745,7 +745,7 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
         */
        ocfs2_probe_alloc_group(inode, gd_bh, &goal_bit, len, move_max_hop,
                                new_phys_cpos);
-       if (!new_phys_cpos) {
+       if (!*new_phys_cpos) {
                ret = -ENOSPC;
                goto out_commit;
        }
index 409285854f647e2357223bc7a8d24c36b376a6bb..d355e6e36b366bfe7dc8cc91cbabdad05976ba2c 100644 (file)
@@ -836,18 +836,65 @@ static inline unsigned int ocfs2_clusters_to_megabytes(struct super_block *sb,
 
 static inline void _ocfs2_set_bit(unsigned int bit, unsigned long *bitmap)
 {
-       __test_and_set_bit_le(bit, bitmap);
+       __set_bit_le(bit, bitmap);
 }
 #define ocfs2_set_bit(bit, addr) _ocfs2_set_bit((bit), (unsigned long *)(addr))
 
 static inline void _ocfs2_clear_bit(unsigned int bit, unsigned long *bitmap)
 {
-       __test_and_clear_bit_le(bit, bitmap);
+       __clear_bit_le(bit, bitmap);
 }
 #define ocfs2_clear_bit(bit, addr) _ocfs2_clear_bit((bit), (unsigned long *)(addr))
 
 #define ocfs2_test_bit test_bit_le
 #define ocfs2_find_next_zero_bit find_next_zero_bit_le
 #define ocfs2_find_next_bit find_next_bit_le
+
+static inline void *correct_addr_and_bit_unaligned(int *bit, void *addr)
+{
+#if BITS_PER_LONG == 64
+       *bit += ((unsigned long) addr & 7UL) << 3;
+       addr = (void *) ((unsigned long) addr & ~7UL);
+#elif BITS_PER_LONG == 32
+       *bit += ((unsigned long) addr & 3UL) << 3;
+       addr = (void *) ((unsigned long) addr & ~3UL);
+#else
+#error "how many bits you are?!"
+#endif
+       return addr;
+}
+
+static inline void ocfs2_set_bit_unaligned(int bit, void *bitmap)
+{
+       bitmap = correct_addr_and_bit_unaligned(&bit, bitmap);
+       ocfs2_set_bit(bit, bitmap);
+}
+
+static inline void ocfs2_clear_bit_unaligned(int bit, void *bitmap)
+{
+       bitmap = correct_addr_and_bit_unaligned(&bit, bitmap);
+       ocfs2_clear_bit(bit, bitmap);
+}
+
+static inline int ocfs2_test_bit_unaligned(int bit, void *bitmap)
+{
+       bitmap = correct_addr_and_bit_unaligned(&bit, bitmap);
+       return ocfs2_test_bit(bit, bitmap);
+}
+
+static inline int ocfs2_find_next_zero_bit_unaligned(void *bitmap, int max,
+                                                       int start)
+{
+       int fix = 0, ret, tmpmax;
+       bitmap = correct_addr_and_bit_unaligned(&fix, bitmap);
+       tmpmax = max + fix;
+       start += fix;
+
+       ret = ocfs2_find_next_zero_bit(bitmap, tmpmax, start) - fix;
+       if (ret > max)
+               return max;
+       return ret;
+}
+
 #endif  /* OCFS2_H */
 
index dc8007fc924718c6d461b22cee52e4a8fbd6ae7d..f100bf70a9066ed1b917b8ec0451c27231840f92 100644 (file)
@@ -404,7 +404,9 @@ struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery(
        int status = 0;
        struct ocfs2_quota_recovery *rec;
 
-       mlog(ML_NOTICE, "Beginning quota recovery in slot %u\n", slot_num);
+       printk(KERN_NOTICE "ocfs2: Beginning quota recovery on device (%s) for "
+              "slot %u\n", osb->dev_str, slot_num);
+
        rec = ocfs2_alloc_quota_recovery();
        if (!rec)
                return ERR_PTR(-ENOMEM);
@@ -549,8 +551,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
                                goto out_commit;
                        }
                        lock_buffer(qbh);
-                       WARN_ON(!ocfs2_test_bit(bit, dchunk->dqc_bitmap));
-                       ocfs2_clear_bit(bit, dchunk->dqc_bitmap);
+                       WARN_ON(!ocfs2_test_bit_unaligned(bit, dchunk->dqc_bitmap));
+                       ocfs2_clear_bit_unaligned(bit, dchunk->dqc_bitmap);
                        le32_add_cpu(&dchunk->dqc_free, 1);
                        unlock_buffer(qbh);
                        ocfs2_journal_dirty(handle, qbh);
@@ -596,7 +598,9 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
        struct inode *lqinode;
        unsigned int flags;
 
-       mlog(ML_NOTICE, "Finishing quota recovery in slot %u\n", slot_num);
+       printk(KERN_NOTICE "ocfs2: Finishing quota recovery on device (%s) for "
+              "slot %u\n", osb->dev_str, slot_num);
+
        mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
        for (type = 0; type < MAXQUOTAS; type++) {
                if (list_empty(&(rec->r_list[type])))
@@ -612,8 +616,9 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
                /* Someone else is holding the lock? Then he must be
                 * doing the recovery. Just skip the file... */
                if (status == -EAGAIN) {
-                       mlog(ML_NOTICE, "skipping quota recovery for slot %d "
-                            "because quota file is locked.\n", slot_num);
+                       printk(KERN_NOTICE "ocfs2: Skipping quota recovery on "
+                              "device (%s) for slot %d because quota file is "
+                              "locked.\n", osb->dev_str, slot_num);
                        status = 0;
                        goto out_put;
                } else if (status < 0) {
@@ -944,7 +949,7 @@ static struct ocfs2_quota_chunk *ocfs2_find_free_entry(struct super_block *sb,
                      * ol_quota_entries_per_block(sb);
        }
 
-       found = ocfs2_find_next_zero_bit(dchunk->dqc_bitmap, len, 0);
+       found = ocfs2_find_next_zero_bit_unaligned(dchunk->dqc_bitmap, len, 0);
        /* We failed? */
        if (found == len) {
                mlog(ML_ERROR, "Did not find empty entry in chunk %d with %u"
@@ -1208,7 +1213,7 @@ static void olq_alloc_dquot(struct buffer_head *bh, void *private)
        struct ocfs2_local_disk_chunk *dchunk;
 
        dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
-       ocfs2_set_bit(*offset, dchunk->dqc_bitmap);
+       ocfs2_set_bit_unaligned(*offset, dchunk->dqc_bitmap);
        le32_add_cpu(&dchunk->dqc_free, -1);
 }
 
@@ -1289,7 +1294,7 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot)
                        (od->dq_chunk->qc_headerbh->b_data);
        /* Mark structure as freed */
        lock_buffer(od->dq_chunk->qc_headerbh);
-       ocfs2_clear_bit(offset, dchunk->dqc_bitmap);
+       ocfs2_clear_bit_unaligned(offset, dchunk->dqc_bitmap);
        le32_add_cpu(&dchunk->dqc_free, 1);
        unlock_buffer(od->dq_chunk->qc_headerbh);
        ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh);
index 26fc0014d50936137d0afb898b7c9541e8026087..1424c151cccce0170819ce4e0f36dad7d97461b8 100644 (file)
@@ -493,8 +493,8 @@ int ocfs2_find_slot(struct ocfs2_super *osb)
                        goto bail;
                }
        } else
-               mlog(ML_NOTICE, "slot %d is already allocated to this node!\n",
-                    slot);
+               printk(KERN_INFO "ocfs2: Slot %d on device (%s) was already "
+                      "allocated to this node!\n", slot, osb->dev_str);
 
        ocfs2_set_slot(si, slot, osb->node_num);
        osb->slot_num = slot;
index 19965b00c43caee7df4e09428775a55150ba9f8c..94368017edb378ce1e3961d1976408c954677c9a 100644 (file)
@@ -28,6 +28,7 @@
 #include "cluster/masklog.h"
 #include "cluster/nodemanager.h"
 #include "cluster/heartbeat.h"
+#include "cluster/tcp.h"
 
 #include "stackglue.h"
 
@@ -255,6 +256,61 @@ static void o2cb_dump_lksb(struct ocfs2_dlm_lksb *lksb)
        dlm_print_one_lock(lksb->lksb_o2dlm.lockid);
 }
 
+/*
+ * Check if this node is heartbeating and is connected to all other
+ * heartbeating nodes.
+ */
+static int o2cb_cluster_check(void)
+{
+       u8 node_num;
+       int i;
+       unsigned long hbmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+       unsigned long netmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+
+       node_num = o2nm_this_node();
+       if (node_num == O2NM_MAX_NODES) {
+               printk(KERN_ERR "o2cb: This node has not been configured.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * o2dlm expects o2net sockets to be created. If not, then
+        * dlm_join_domain() fails with a stack of errors which are both cryptic
+        * and incomplete. The idea here is to detect upfront whether we have
+        * managed to connect to all nodes or not. If not, then list the nodes
+        * to allow the user to check the configuration (incorrect IP, firewall,
+        * etc.) Yes, this is racy. But its not the end of the world.
+        */
+#define        O2CB_MAP_STABILIZE_COUNT        60
+       for (i = 0; i < O2CB_MAP_STABILIZE_COUNT; ++i) {
+               o2hb_fill_node_map(hbmap, sizeof(hbmap));
+               if (!test_bit(node_num, hbmap)) {
+                       printk(KERN_ERR "o2cb: %s heartbeat has not been "
+                              "started.\n", (o2hb_global_heartbeat_active() ?
+                                             "Global" : "Local"));
+                       return -EINVAL;
+               }
+               o2net_fill_node_map(netmap, sizeof(netmap));
+               /* Force set the current node to allow easy compare */
+               set_bit(node_num, netmap);
+               if (!memcmp(hbmap, netmap, sizeof(hbmap)))
+                       return 0;
+               if (i < O2CB_MAP_STABILIZE_COUNT)
+                       msleep(1000);
+       }
+
+       printk(KERN_ERR "o2cb: This node could not connect to nodes:");
+       i = -1;
+       while ((i = find_next_bit(hbmap, O2NM_MAX_NODES,
+                                 i + 1)) < O2NM_MAX_NODES) {
+               if (!test_bit(i, netmap))
+                       printk(" %u", i);
+       }
+       printk(".\n");
+
+       return -ENOTCONN;
+}
+
 /*
  * Called from the dlm when it's about to evict a node. This is how the
  * classic stack signals node death.
@@ -263,8 +319,8 @@ static void o2dlm_eviction_cb(int node_num, void *data)
 {
        struct ocfs2_cluster_connection *conn = data;
 
-       mlog(ML_NOTICE, "o2dlm has evicted node %d from group %.*s\n",
-            node_num, conn->cc_namelen, conn->cc_name);
+       printk(KERN_NOTICE "o2cb: o2dlm has evicted node %d from domain %.*s\n",
+              node_num, conn->cc_namelen, conn->cc_name);
 
        conn->cc_recovery_handler(node_num, conn->cc_recovery_data);
 }
@@ -280,12 +336,11 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn)
        BUG_ON(conn == NULL);
        BUG_ON(conn->cc_proto == NULL);
 
-       /* for now we only have one cluster/node, make sure we see it
-        * in the heartbeat universe */
-       if (!o2hb_check_local_node_heartbeating()) {
-               if (o2hb_global_heartbeat_active())
-                       mlog(ML_ERROR, "Global heartbeat not started\n");
-               rc = -EINVAL;
+       /* Ensure cluster stack is up and all nodes are connected */
+       rc = o2cb_cluster_check();
+       if (rc) {
+               printk(KERN_ERR "o2cb: Cluster check failed. Fix errors "
+                      "before retrying.\n");
                goto out;
        }
 
index 56f61027236b696fce1ccde3e1edaf86acee59a0..4994f8b0e60410ff576fa63299e29e430192080a 100644 (file)
@@ -54,6 +54,7 @@
 #include "ocfs1_fs_compat.h"
 
 #include "alloc.h"
+#include "aops.h"
 #include "blockcheck.h"
 #include "dlmglue.h"
 #include "export.h"
@@ -1107,9 +1108,9 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
                ocfs2_set_ro_flag(osb, 1);
 
-               printk(KERN_NOTICE "Readonly device detected. No cluster "
-                      "services will be utilized for this mount. Recovery "
-                      "will be skipped.\n");
+               printk(KERN_NOTICE "ocfs2: Readonly device (%s) detected. "
+                      "Cluster services will not be used for this mount. "
+                      "Recovery will be skipped.\n", osb->dev_str);
        }
 
        if (!ocfs2_is_hard_readonly(osb)) {
@@ -1616,12 +1617,17 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        return 0;
 }
 
+wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ];
+
 static int __init ocfs2_init(void)
 {
-       int status;
+       int status, i;
 
        ocfs2_print_version();
 
+       for (i = 0; i < OCFS2_IOEND_WQ_HASH_SZ; i++)
+               init_waitqueue_head(&ocfs2__ioend_wq[i]);
+
        status = init_ocfs2_uptodate_cache();
        if (status < 0) {
                mlog_errno(status);
@@ -1760,7 +1766,7 @@ static void ocfs2_inode_init_once(void *data)
        ocfs2_extent_map_init(&oi->vfs_inode);
        INIT_LIST_HEAD(&oi->ip_io_markers);
        oi->ip_dir_start_lookup = 0;
-
+       atomic_set(&oi->ip_unaligned_aio, 0);
        init_rwsem(&oi->ip_alloc_sem);
        init_rwsem(&oi->ip_xattr_sem);
        mutex_init(&oi->ip_io_mutex);
@@ -1974,7 +1980,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
         * If we failed before we got a uuid_str yet, we can't stop
         * heartbeat.  Otherwise, do it.
         */
-       if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str)
+       if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str &&
+           !ocfs2_is_hard_readonly(osb))
                hangup_needed = 1;
 
        if (osb->cconn)
@@ -2353,7 +2360,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
                mlog_errno(status);
                goto bail;
        }
-       cleancache_init_shared_fs((char *)&uuid_net_key, sb);
+       cleancache_init_shared_fs((char *)&di->id2.i_super.s_uuid, sb);
 
 bail:
        return status;
@@ -2462,8 +2469,8 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
                        goto finally;
                }
        } else {
-               mlog(ML_NOTICE, "File system was not unmounted cleanly, "
-                    "recovering volume.\n");
+               printk(KERN_NOTICE "ocfs2: File system on device (%s) was not "
+                      "unmounted cleanly, recovering it.\n", osb->dev_str);
        }
 
        local = ocfs2_mount_local(osb);
index 194fb22ef79d590580f3245b522d0b095ef3794c..aa9e8777b09a5e345b081b0e495db378485a30e7 100644 (file)
@@ -2376,16 +2376,18 @@ static int ocfs2_remove_value_outside(struct inode*inode,
                }
 
                ret = ocfs2_xattr_value_truncate(inode, vb, 0, &ctxt);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       break;
-               }
 
                ocfs2_commit_trans(osb, ctxt.handle);
                if (ctxt.meta_ac) {
                        ocfs2_free_alloc_context(ctxt.meta_ac);
                        ctxt.meta_ac = NULL;
                }
+
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       break;
+               }
+
        }
 
        if (ctxt.meta_ac)
index 2db1bd3173b2d77bb902273173a8ede14bf27f2e..851ba3dcdc290ab6b750793c2840bdffac755de7 100644 (file)
@@ -1652,46 +1652,12 @@ out:
        return error;
 }
 
-static int proc_pid_fd_link_getattr(struct vfsmount *mnt, struct dentry *dentry,
-               struct kstat *stat)
-{
-       struct inode *inode = dentry->d_inode;
-       struct task_struct *task = get_proc_task(inode);
-       int rc;
-
-       if (task == NULL)
-               return -ESRCH;
-
-       rc = -EACCES;
-       if (lock_trace(task))
-               goto out_task;
-
-       generic_fillattr(inode, stat);
-       unlock_trace(task);
-       rc = 0;
-out_task:
-       put_task_struct(task);
-       return rc;
-}
-
 static const struct inode_operations proc_pid_link_inode_operations = {
        .readlink       = proc_pid_readlink,
        .follow_link    = proc_pid_follow_link,
        .setattr        = proc_setattr,
 };
 
-static const struct inode_operations proc_fdinfo_link_inode_operations = {
-       .setattr        = proc_setattr,
-       .getattr        = proc_pid_fd_link_getattr,
-};
-
-static const struct inode_operations proc_fd_link_inode_operations = {
-       .readlink       = proc_pid_readlink,
-       .follow_link    = proc_pid_follow_link,
-       .setattr        = proc_setattr,
-       .getattr        = proc_pid_fd_link_getattr,
-};
-
 
 /* building an inode */
 
@@ -1923,61 +1889,49 @@ out:
 
 static int proc_fd_info(struct inode *inode, struct path *path, char *info)
 {
-       struct task_struct *task;
-       struct files_struct *files;
+       struct task_struct *task = get_proc_task(inode);
+       struct files_struct *files = NULL;
        struct file *file;
        int fd = proc_fd(inode);
-       int rc;
-
-       task = get_proc_task(inode);
-       if (!task)
-               return -ENOENT;
-
-       rc = -EACCES;
-       if (lock_trace(task))
-               goto out_task;
-
-       rc = -ENOENT;
-       files = get_files_struct(task);
-       if (files == NULL)
-               goto out_unlock;
 
-       /*
-        * We are not taking a ref to the file structure, so we must
-        * hold ->file_lock.
-        */
-       spin_lock(&files->file_lock);
-       file = fcheck_files(files, fd);
-       if (file) {
-               unsigned int f_flags;
-               struct fdtable *fdt;
-
-               fdt = files_fdtable(files);
-               f_flags = file->f_flags & ~O_CLOEXEC;
-               if (FD_ISSET(fd, fdt->close_on_exec))
-                       f_flags |= O_CLOEXEC;
-
-               if (path) {
-                       *path = file->f_path;
-                       path_get(&file->f_path);
+       if (task) {
+               files = get_files_struct(task);
+               put_task_struct(task);
+       }
+       if (files) {
+               /*
+                * We are not taking a ref to the file structure, so we must
+                * hold ->file_lock.
+                */
+               spin_lock(&files->file_lock);
+               file = fcheck_files(files, fd);
+               if (file) {
+                       unsigned int f_flags;
+                       struct fdtable *fdt;
+
+                       fdt = files_fdtable(files);
+                       f_flags = file->f_flags & ~O_CLOEXEC;
+                       if (FD_ISSET(fd, fdt->close_on_exec))
+                               f_flags |= O_CLOEXEC;
+
+                       if (path) {
+                               *path = file->f_path;
+                               path_get(&file->f_path);
+                       }
+                       if (info)
+                               snprintf(info, PROC_FDINFO_MAX,
+                                        "pos:\t%lli\n"
+                                        "flags:\t0%o\n",
+                                        (long long) file->f_pos,
+                                        f_flags);
+                       spin_unlock(&files->file_lock);
+                       put_files_struct(files);
+                       return 0;
                }
-               if (info)
-                       snprintf(info, PROC_FDINFO_MAX,
-                                "pos:\t%lli\n"
-                                "flags:\t0%o\n",
-                                (long long) file->f_pos,
-                                f_flags);
-               rc = 0;
-       } else
-               rc = -ENOENT;
-       spin_unlock(&files->file_lock);
-       put_files_struct(files);
-
-out_unlock:
-       unlock_trace(task);
-out_task:
-       put_task_struct(task);
-       return rc;
+               spin_unlock(&files->file_lock);
+               put_files_struct(files);
+       }
+       return -ENOENT;
 }
 
 static int proc_fd_link(struct inode *inode, struct path *path)
@@ -2072,7 +2026,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
        spin_unlock(&files->file_lock);
        put_files_struct(files);
 
-       inode->i_op = &proc_fd_link_inode_operations;
+       inode->i_op = &proc_pid_link_inode_operations;
        inode->i_size = 64;
        ei->op.proc_get_link = proc_fd_link;
        d_set_d_op(dentry, &tid_fd_dentry_operations);
@@ -2104,12 +2058,7 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
        if (fd == ~0U)
                goto out;
 
-       result = ERR_PTR(-EACCES);
-       if (lock_trace(task))
-               goto out;
-
        result = instantiate(dir, dentry, task, &fd);
-       unlock_trace(task);
 out:
        put_task_struct(task);
 out_no_task:
@@ -2129,28 +2078,23 @@ static int proc_readfd_common(struct file * filp, void * dirent,
        retval = -ENOENT;
        if (!p)
                goto out_no_task;
-
-       retval = -EACCES;
-       if (lock_trace(p))
-               goto out;
-
        retval = 0;
 
        fd = filp->f_pos;
        switch (fd) {
                case 0:
                        if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
-                               goto out_unlock;
+                               goto out;
                        filp->f_pos++;
                case 1:
                        ino = parent_ino(dentry);
                        if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
-                               goto out_unlock;
+                               goto out;
                        filp->f_pos++;
                default:
                        files = get_files_struct(p);
                        if (!files)
-                               goto out_unlock;
+                               goto out;
                        rcu_read_lock();
                        for (fd = filp->f_pos-2;
                             fd < files_fdtable(files)->max_fds;
@@ -2174,9 +2118,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
                        rcu_read_unlock();
                        put_files_struct(files);
        }
-
-out_unlock:
-       unlock_trace(p);
 out:
        put_task_struct(p);
 out_no_task:
@@ -2254,7 +2195,6 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
        ei->fd = fd;
        inode->i_mode = S_IFREG | S_IRUSR;
        inode->i_fop = &proc_fdinfo_file_operations;
-       inode->i_op = &proc_fdinfo_link_inode_operations;
        d_set_d_op(dentry, &tid_fd_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
index 2bd620f0d796cf5dee01590c65b7ac8802e33bf9..57bbf9078ac8f327be28e88b38e10eeff1f9bfc0 100644 (file)
@@ -167,6 +167,7 @@ int pstore_register(struct pstore_info *psi)
        }
 
        psinfo = psi;
+       mutex_init(&psinfo->read_mutex);
        spin_unlock(&pstore_lock);
 
        if (owner && !try_module_get(owner)) {
@@ -195,30 +196,32 @@ EXPORT_SYMBOL_GPL(pstore_register);
 void pstore_get_records(int quiet)
 {
        struct pstore_info *psi = psinfo;
+       char                    *buf = NULL;
        ssize_t                 size;
        u64                     id;
        enum pstore_type_id     type;
        struct timespec         time;
        int                     failed = 0, rc;
-       unsigned long           flags;
 
        if (!psi)
                return;
 
-       spin_lock_irqsave(&psinfo->buf_lock, flags);
+       mutex_lock(&psi->read_mutex);
        rc = psi->open(psi);
        if (rc)
                goto out;
 
-       while ((size = psi->read(&id, &type, &time, psi)) > 0) {
-               rc = pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
+       while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) {
+               rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size,
                                  time, psi);
+               kfree(buf);
+               buf = NULL;
                if (rc && (rc != -EEXIST || !quiet))
                        failed++;
        }
        psi->close(psi);
 out:
-       spin_unlock_irqrestore(&psinfo->buf_lock, flags);
+       mutex_unlock(&psi->read_mutex);
 
        if (failed)
                printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
index eef109a1a92772d67cfe7a5693e113c8c801dbec..b09ba2dd8b625efc12130e7a20572560072d8b3b 100644 (file)
@@ -870,6 +870,22 @@ void dbg_dump_lpt_info(struct ubifs_info *c)
        spin_unlock(&dbg_lock);
 }
 
+void dbg_dump_sleb(const struct ubifs_info *c,
+                  const struct ubifs_scan_leb *sleb, int offs)
+{
+       struct ubifs_scan_node *snod;
+
+       printk(KERN_DEBUG "(pid %d) start dumping scanned data from LEB %d:%d\n",
+              current->pid, sleb->lnum, offs);
+
+       list_for_each_entry(snod, &sleb->nodes, list) {
+               cond_resched();
+               printk(KERN_DEBUG "Dumping node at LEB %d:%d len %d\n", sleb->lnum,
+                      snod->offs, snod->len);
+               dbg_dump_node(c, snod->node);
+       }
+}
+
 void dbg_dump_leb(const struct ubifs_info *c, int lnum)
 {
        struct ubifs_scan_leb *sleb;
index feb361e252acfe801d186849430c553e39a4268e..8d9c46810189a1db050d047a11b521c8fe145dba 100644 (file)
@@ -269,6 +269,8 @@ void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
 void dbg_dump_lprops(struct ubifs_info *c);
 void dbg_dump_lpt_info(struct ubifs_info *c);
 void dbg_dump_leb(const struct ubifs_info *c, int lnum);
+void dbg_dump_sleb(const struct ubifs_info *c,
+                  const struct ubifs_scan_leb *sleb, int offs);
 void dbg_dump_znode(const struct ubifs_info *c,
                    const struct ubifs_znode *znode);
 void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat);
@@ -387,6 +389,9 @@ static inline void dbg_dump_lpt_info(struct ubifs_info *c)        { return; }
 static inline void dbg_dump_leb(const struct ubifs_info *c,
                                int lnum)                         { return; }
 static inline void
+dbg_dump_sleb(const struct ubifs_info *c,
+             const struct ubifs_scan_leb *sleb, int offs)        { return; }
+static inline void
 dbg_dump_znode(const struct ubifs_info *c,
               const struct ubifs_znode *znode)                   { return; }
 static inline void dbg_dump_heap(struct ubifs_info *c,
index af02790d93282ec55c3ba48c3efca155b5ddea89..ee4f43f4bb998d2bc20ac1f96437e926e2f2e490 100644 (file)
@@ -983,7 +983,7 @@ int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf)
 }
 
 /**
- *  clean_an_unclean_leb - read and write a LEB to remove corruption.
+ * clean_an_unclean_leb - read and write a LEB to remove corruption.
  * @c: UBIFS file-system description object
  * @ucleb: unclean LEB information
  * @sbuf: LEB-sized buffer to use
index 93d938ad3d2a74ec74d56a5d64aba6860a44eb10..6094c5a5d7a8de597e3905b9c4941f458cc999f3 100644 (file)
@@ -247,7 +247,7 @@ static int create_default_filesystem(struct ubifs_info *c)
        mst->total_dirty = cpu_to_le64(tmp64);
 
        /*  The indexing LEB does not contribute to dark space */
-       tmp64 = (c->main_lebs - 1) * c->dark_wm;
+       tmp64 = ((long long)(c->main_lebs - 1) * c->dark_wm);
        mst->total_dark = cpu_to_le64(tmp64);
 
        mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ);
index 33b13310ee0c2f2ddf0c68abaa57e95c7f47d963..574d4ee9b6253ea3d589f23288aa7385907642bb 100644 (file)
@@ -189,7 +189,7 @@ xfs_end_io(
        int             error = 0;
 
        if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-               error = -EIO;
+               ioend->io_error = -EIO;
                goto done;
        }
        if (ioend->io_error)
index 1a3513881bce749d7d4510c2ed21f47bda02a926..eac97ef81e2a156a58d9b74b54607c6a0d2e76c3 100644 (file)
@@ -656,7 +656,7 @@ xfs_buf_item_committing(
 /*
  * This is the ops vector shared by all buf log items.
  */
-static struct xfs_item_ops xfs_buf_item_ops = {
+static const struct xfs_item_ops xfs_buf_item_ops = {
        .iop_size       = xfs_buf_item_size,
        .iop_format     = xfs_buf_item_format,
        .iop_pin        = xfs_buf_item_pin,
index bb3f71d236d28fe8e5733e8264e693a0b00692d6..0dee0b71029d8406add271b9f20350e6b8a97859 100644 (file)
@@ -295,7 +295,7 @@ xfs_qm_dquot_logitem_committing(
 /*
  * This is the ops vector for dquots
  */
-static struct xfs_item_ops xfs_dquot_item_ops = {
+static const struct xfs_item_ops xfs_dquot_item_ops = {
        .iop_size       = xfs_qm_dquot_logitem_size,
        .iop_format     = xfs_qm_dquot_logitem_format,
        .iop_pin        = xfs_qm_dquot_logitem_pin,
@@ -483,7 +483,7 @@ xfs_qm_qoff_logitem_committing(
 {
 }
 
-static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
+static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
        .iop_size       = xfs_qm_qoff_logitem_size,
        .iop_format     = xfs_qm_qoff_logitem_format,
        .iop_pin        = xfs_qm_qoff_logitem_pin,
@@ -498,7 +498,7 @@ static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
 /*
  * This is the ops vector shared by all quotaoff-start log items.
  */
-static struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
+static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
        .iop_size       = xfs_qm_qoff_logitem_size,
        .iop_format     = xfs_qm_qoff_logitem_format,
        .iop_pin        = xfs_qm_qoff_logitem_pin,
index d22e62623437aafb79d62f5492252e140f3a6cb7..35c2aff38b209bd0afa1ff5b36e20230a1d3b5c5 100644 (file)
@@ -217,7 +217,7 @@ xfs_efi_item_committing(
 /*
  * This is the ops vector shared by all efi log items.
  */
-static struct xfs_item_ops xfs_efi_item_ops = {
+static const struct xfs_item_ops xfs_efi_item_ops = {
        .iop_size       = xfs_efi_item_size,
        .iop_format     = xfs_efi_item_format,
        .iop_pin        = xfs_efi_item_pin,
@@ -477,7 +477,7 @@ xfs_efd_item_committing(
 /*
  * This is the ops vector shared by all efd log items.
  */
-static struct xfs_item_ops xfs_efd_item_ops = {
+static const struct xfs_item_ops xfs_efd_item_ops = {
        .iop_size       = xfs_efd_item_size,
        .iop_format     = xfs_efd_item_format,
        .iop_pin        = xfs_efd_item_pin,
index b7cf21ba240f802ea56c26a45be341d55641a7dd..abaafdbb3e658e9c484fb82dcfd5b63afade43e9 100644 (file)
@@ -795,7 +795,7 @@ xfs_inode_item_committing(
 /*
  * This is the ops vector shared by all buf log items.
  */
-static struct xfs_item_ops xfs_inode_item_ops = {
+static const struct xfs_item_ops xfs_inode_item_ops = {
        .iop_size       = xfs_inode_item_size,
        .iop_format     = xfs_inode_item_format,
        .iop_pin        = xfs_inode_item_pin,
index 2758a6277c525998f47a6a4d59e8bbc1e9e7ee3a..a14cd89fe4655e2647d92d2191c1ffb8e6588787 100644 (file)
@@ -626,7 +626,7 @@ xfs_log_item_init(
        struct xfs_mount        *mp,
        struct xfs_log_item     *item,
        int                     type,
-       struct xfs_item_ops     *ops)
+       const struct xfs_item_ops *ops)
 {
        item->li_mountp = mp;
        item->li_ailp = mp->m_ail;
index 78c9039994afab9739c4f338a62741aea8bd17cb..3f7bf451c03446f920484a03eb6e073706127a2f 100644 (file)
@@ -137,7 +137,7 @@ struct xfs_trans;
 void   xfs_log_item_init(struct xfs_mount      *mp,
                        struct xfs_log_item     *item,
                        int                     type,
-                       struct xfs_item_ops     *ops);
+                       const struct xfs_item_ops *ops);
 
 xfs_lsn_t xfs_log_done(struct xfs_mount *mp,
                       struct xlog_ticket *ticket,
index 5cff443f6cdb782f4d89cfed6e767bdb24a32e06..0bbb1a41998bc95563813ef8a584e104aad5c462 100644 (file)
@@ -674,7 +674,8 @@ xfs_qm_dqattach_one(
         * disk and we didn't ask it to allocate;
         * ESRCH if quotas got turned off suddenly.
         */
-       error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp);
+       error = xfs_qm_dqget(ip->i_mount, ip, id, type,
+                            doalloc | XFS_QMOPT_DOWARN, &dqp);
        if (error)
                return error;
 
index 603f3eb52041ef84b89177956ff74ffc6ef1a114..3ae713c0abd9a04b3964d3ff8a9305155cd3b97a 100644 (file)
@@ -326,7 +326,7 @@ typedef struct xfs_log_item {
                                                 struct xfs_log_item *);
                                                        /* buffer item iodone */
                                                        /* callback func */
-       struct xfs_item_ops             *li_ops;        /* function list */
+       const struct xfs_item_ops       *li_ops;        /* function list */
 
        /* delayed logging */
        struct list_head                li_cil;         /* CIL pointers */
@@ -341,7 +341,7 @@ typedef struct xfs_log_item {
        { XFS_LI_IN_AIL,        "IN_AIL" }, \
        { XFS_LI_ABORTED,       "ABORTED" }
 
-typedef struct xfs_item_ops {
+struct xfs_item_ops {
        uint (*iop_size)(xfs_log_item_t *);
        void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *);
        void (*iop_pin)(xfs_log_item_t *);
@@ -352,7 +352,7 @@ typedef struct xfs_item_ops {
        void (*iop_push)(xfs_log_item_t *);
        bool (*iop_pushbuf)(xfs_log_item_t *);
        void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
-} xfs_item_ops_t;
+};
 
 #define IOP_SIZE(ip)           (*(ip)->li_ops->iop_size)(ip)
 #define IOP_FORMAT(ip,vp)      (*(ip)->li_ops->iop_format)(ip, vp)
index 4ecf2a549060295b0d354847a538eba890083631..ce9268a2f56be487a161b950d36fc88590877c29 100644 (file)
@@ -112,7 +112,7 @@ xfs_readlink(
        char            *link)
 {
        xfs_mount_t     *mp = ip->i_mount;
-       int             pathlen;
+       xfs_fsize_t     pathlen;
        int             error = 0;
 
        trace_xfs_readlink(ip);
@@ -122,13 +122,19 @@ xfs_readlink(
 
        xfs_ilock(ip, XFS_ILOCK_SHARED);
 
-       ASSERT(S_ISLNK(ip->i_d.di_mode));
-       ASSERT(ip->i_d.di_size <= MAXPATHLEN);
-
        pathlen = ip->i_d.di_size;
        if (!pathlen)
                goto out;
 
+       if (pathlen < 0 || pathlen > MAXPATHLEN) {
+               xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
+                        __func__, (unsigned long long) ip->i_ino,
+                        (long long) pathlen);
+               ASSERT(0);
+               return XFS_ERROR(EFSCORRUPTED);
+       }
+
+
        if (ip->i_df.if_flags & XFS_IFINLINE) {
                memcpy(link, ip->i_df.if_u1.if_data, pathlen);
                link[pathlen] = '\0';
index e49c36d38d7ee23900f60c20ef826ea969f0fd21..bb145e4b935e79760146f17d5f6bd4c70843278d 100644 (file)
@@ -144,7 +144,7 @@ static inline void unregister_dock_notifier(struct notifier_block *nb)
 {
 }
 static inline int register_hotplug_dock_device(acpi_handle handle,
-                                              struct acpi_dock_ops *ops,
+                                              const struct acpi_dock_ops *ops,
                                               void *context)
 {
        return -ENODEV;
index b67231bef632714add11abf65eac32c82cda4dd6..ed73f6705c860d2bc8c28db91b7191c13c144b31 100644 (file)
@@ -470,7 +470,6 @@ typedef u64 acpi_integer;
  */
 #define ACPI_FULL_INITIALIZATION        0x00
 #define ACPI_NO_ADDRESS_SPACE_INIT      0x01
-#define ACPI_NO_HARDWARE_INIT           0x02
 #define ACPI_NO_EVENT_INIT              0x04
 #define ACPI_NO_HANDLER_INIT            0x08
 #define ACPI_NO_ACPI_ENABLE             0x10
index 67055f180330b6a59f653833ebe51c8afd151a29..610f6fb1bbc2ed71109c3ad4e290d51febbb4376 100644 (file)
@@ -329,6 +329,7 @@ extern void acpi_processor_throttling_init(void);
 int acpi_processor_power_init(struct acpi_processor *pr,
                              struct acpi_device *device);
 int acpi_processor_cst_has_changed(struct acpi_processor *pr);
+int acpi_processor_hotplug(struct acpi_processor *pr);
 int acpi_processor_power_exit(struct acpi_processor *pr,
                              struct acpi_device *device);
 int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
index cf399495d38ff7418947471e164faa79c0a094ec..1f9e9516e2b75da38aa87abbf774d1505803cc98 100644 (file)
@@ -990,7 +990,9 @@ struct drm_minor {
        struct proc_dir_entry *proc_root;  /**< proc directory entry */
        struct drm_info_node proc_nodes;
        struct dentry *debugfs_root;
-       struct drm_info_node debugfs_nodes;
+
+       struct list_head debugfs_list;
+       struct mutex debugfs_lock; /* Protects debugfs_list. */
 
        struct drm_master *master; /* currently active master for this node */
        struct list_head master_list;
index 0d2f727e96be8dd1e29c65e64f06c664f6d1992d..93df2d72750b1878e8822bf8716b77926941ae91 100644 (file)
@@ -72,6 +72,7 @@
 
 #define DP_MAIN_LINK_CHANNEL_CODING         0x006
 
+#define DP_EDP_CONFIGURATION_CAP            0x00d
 #define DP_TRAINING_AUX_RD_INTERVAL         0x00e
 
 #define DP_PSR_SUPPORT                      0x070
 # define DP_CP_IRQ                         (1 << 2)
 # define DP_SINK_SPECIFIC_IRQ              (1 << 6)
 
+#define DP_EDP_CONFIGURATION_SET            0x10a
+
 #define DP_LANE0_1_STATUS                  0x202
 #define DP_LANE2_3_STATUS                  0x203
 # define DP_LANE_CR_DONE                   (1 << 0)
index c4961ea50a494b69d996873e09e8e509956660c0..ddd46db65b57257164f13d703186bb7da5e7bb3a 100644 (file)
@@ -120,11 +120,12 @@ struct drm_mode_crtc {
        struct drm_mode_modeinfo mode;
 };
 
-#define DRM_MODE_ENCODER_NONE  0
-#define DRM_MODE_ENCODER_DAC   1
-#define DRM_MODE_ENCODER_TMDS  2
-#define DRM_MODE_ENCODER_LVDS  3
-#define DRM_MODE_ENCODER_TVDAC 4
+#define DRM_MODE_ENCODER_NONE   0
+#define DRM_MODE_ENCODER_DAC    1
+#define DRM_MODE_ENCODER_TMDS   2
+#define DRM_MODE_ENCODER_LVDS   3
+#define DRM_MODE_ENCODER_TVDAC  4
+#define DRM_MODE_ENCODER_VIRTUAL 5
 
 struct drm_mode_get_encoder {
        __u32 encoder_id;
@@ -162,6 +163,7 @@ struct drm_mode_get_encoder {
 #define DRM_MODE_CONNECTOR_HDMIB       12
 #define DRM_MODE_CONNECTOR_TV          13
 #define DRM_MODE_CONNECTOR_eDP         14
+#define DRM_MODE_CONNECTOR_VIRTUAL      15
 
 struct drm_mode_get_connector {
 
@@ -233,6 +235,8 @@ struct drm_mode_fb_cmd {
 #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
 #define DRM_MODE_FB_DIRTY_FLAGS         0x03
 
+#define DRM_MODE_FB_DIRTY_MAX_CLIPS     256
+
 /*
  * Mark a region of a framebuffer as dirty.
  *
index 3d53efd25ab906889e081acb8ae10f1065ef180a..f81676f1b3105636bde40ebd0c99d5e7265f7600 100644 (file)
@@ -4,6 +4,7 @@
 */
 #define radeon_PCI_IDS \
        {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x3151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x3155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -55,6 +56,7 @@
        {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C6E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
index 874c4d271328572cc96dc5efc5dc4710d9d037fd..12050434d57a248909d695a80445e958dea81e32 100644 (file)
 /**
  * User-desired buffer creation information structure.
  *
- * @size: requested size for the object.
+ * @size: user-desired memory allocation size.
  *     - this size value would be page-aligned internally.
  * @flags: user request for setting memory type or cache attributes.
- * @handle: returned handle for the object.
+ * @handle: returned a handle to created gem object.
+ *     - this handle will be set by gem module of kernel side.
  */
 struct drm_exynos_gem_create {
-       unsigned int size;
+       uint64_t size;
        unsigned int flags;
        unsigned int handle;
 };
index b65be6054a183efe7b0ea5daa7c8afd7b1aa6a72..be94be6d6f17afdd027b3cf61679c73651ac6f9e 100644 (file)
@@ -874,6 +874,10 @@ struct drm_radeon_gem_pwrite {
 
 #define RADEON_CHUNK_ID_RELOCS 0x01
 #define RADEON_CHUNK_ID_IB     0x02
+#define RADEON_CHUNK_ID_FLAGS  0x03
+
+/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */
+#define RADEON_CS_KEEP_TILING_FLAGS 0x01
 
 struct drm_radeon_cs_chunk {
        uint32_t                chunk_id;
index cd7cd8162ed62d4aaba66ea3546c44444dc583db..bcb0912afe7a4a233a171f2d1b4bb7d518c6884e 100644 (file)
@@ -54,7 +54,7 @@
 #define DRM_VMW_FENCE_EVENT          17
 #define DRM_VMW_PRESENT              18
 #define DRM_VMW_PRESENT_READBACK     19
-
+#define DRM_VMW_UPDATE_LAYOUT        20
 
 /*************************************************************************/
 /**
@@ -550,31 +550,6 @@ struct drm_vmw_get_3d_cap_arg {
        uint32_t pad64;
 };
 
-/*************************************************************************/
-/**
- * DRM_VMW_UPDATE_LAYOUT - Update layout
- *
- * Updates the preferred modes and connection status for connectors. The
- * command conisits of one drm_vmw_update_layout_arg pointing out a array
- * of num_outputs drm_vmw_rect's.
- */
-
-/**
- * struct drm_vmw_update_layout_arg
- *
- * @num_outputs: number of active
- * @rects: pointer to array of drm_vmw_rect
- *
- * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
- */
-
-struct drm_vmw_update_layout_arg {
-       uint32_t num_outputs;
-       uint32_t pad64;
-       uint64_t rects;
-};
-
-
 /*************************************************************************/
 /**
  * DRM_VMW_FENCE_WAIT
@@ -788,4 +763,28 @@ struct drm_vmw_present_readback_arg {
         uint64_t clips_ptr;
         uint64_t fence_rep;
 };
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UPDATE_LAYOUT - Update layout
+ *
+ * Updates the preferred modes and connection status for connectors. The
+ * command consists of one drm_vmw_update_layout_arg pointing to an array
+ * of num_outputs drm_vmw_rect's.
+ */
+
+/**
+ * struct drm_vmw_update_layout_arg
+ *
+ * @num_outputs: number of active connectors
+ * @rects: pointer to array of drm_vmw_rect cast to an uint64_t
+ *
+ * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
+ */
+struct drm_vmw_update_layout_arg {
+       uint32_t num_outputs;
+       uint32_t pad64;
+       uint64_t rects;
+};
+
 #endif
index a3c071c9e18934765e44b84d8330e9fd979d6dc4..847994aef0e9755a3a39d76dd42f87c9f43d23be 100644 (file)
@@ -211,8 +211,8 @@ extern void bio_pair_release(struct bio_pair *dbio);
 extern struct bio_set *bioset_create(unsigned int, unsigned int);
 extern void bioset_free(struct bio_set *);
 
-extern struct bio *bio_alloc(gfp_t, int);
-extern struct bio *bio_kmalloc(gfp_t, int);
+extern struct bio *bio_alloc(gfp_t, unsigned int);
+extern struct bio *bio_kmalloc(gfp_t, unsigned int);
 extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
 extern void bio_put(struct bio *);
 extern void bio_free(struct bio *, struct bio_set *);
@@ -519,7 +519,11 @@ extern void bio_integrity_init(void);
 #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, d)        (0)
+static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
+                                     gfp_t gfp_mask, struct bio_set *bs)
+{
+       return 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)
index f88eacb111d4151dc5491797fe0e03faaadc26a9..7c05ac202d90650069d4713ac2e13b3be9b86024 100644 (file)
 #include "osdmap.h"
 #include "messenger.h"
 
+/* 
+ * Maximum object name size 
+ * (must be at least as big as RBD_MAX_MD_NAME_LEN -- currently 100) 
+ */
+#define MAX_OBJ_NAME_SIZE 100
+
 struct ceph_msg;
 struct ceph_snap_context;
 struct ceph_osd_request;
@@ -75,7 +81,7 @@ struct ceph_osd_request {
        struct inode *r_inode;                /* for use by callbacks */
        void *r_priv;                         /* ditto */
 
-       char              r_oid[40];          /* object name */
+       char              r_oid[MAX_OBJ_NAME_SIZE];          /* object name */
        int               r_oid_len;
        unsigned long     r_stamp;            /* send OR check time */
 
index 139c4db55f1736eebc35cc4601ee98d0d10a40c7..c86c940d1de3a58b73fd4027b80524daca997478 100644 (file)
@@ -156,6 +156,7 @@ extern u64 timecounter_cyc2time(struct timecounter *tc,
  * @mult:              cycle to nanosecond multiplier
  * @shift:             cycle to nanosecond divisor (power of two)
  * @max_idle_ns:       max idle time permitted by the clocksource (nsecs)
+ * @maxadj             maximum adjustment value to mult (~11%)
  * @flags:             flags describing special properties
  * @archdata:          arch-specific data
  * @suspend:           suspend function for the clocksource, if necessary
@@ -172,7 +173,7 @@ struct clocksource {
        u32 mult;
        u32 shift;
        u64 max_idle_ns;
-
+       u32 maxadj;
 #ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
        struct arch_clocksource_data archdata;
 #endif
index 583baf22cad20a6082b688d079dd24dd8aa3aa18..7408af843b8ac891b1fd59557c5cb7faa117c0bd 100644 (file)
 struct module;
 
 struct cpuidle_device;
+struct cpuidle_driver;
 
 
 /****************************
  * CPUIDLE DEVICE INTERFACE *
  ****************************/
 
+struct cpuidle_state_usage {
+       void            *driver_data;
+
+       unsigned long long      usage;
+       unsigned long long      time; /* in US */
+};
+
 struct cpuidle_state {
        char            name[CPUIDLE_NAME_LEN];
        char            desc[CPUIDLE_DESC_LEN];
-       void            *driver_data;
 
        unsigned int    flags;
        unsigned int    exit_latency; /* in US */
        unsigned int    power_usage; /* in mW */
        unsigned int    target_residency; /* in US */
 
-       unsigned long long      usage;
-       unsigned long long      time; /* in US */
-
        int (*enter)    (struct cpuidle_device *dev,
-                        struct cpuidle_state *state);
+                       struct cpuidle_driver *drv,
+                       int index);
 };
 
 /* Idle State Flags */
 #define CPUIDLE_FLAG_TIME_VALID        (0x01) /* is residency time measurable? */
-#define CPUIDLE_FLAG_IGNORE    (0x100) /* ignore during this idle period */
 
 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
 
 /**
  * cpuidle_get_statedata - retrieves private driver state data
- * @state: the state
+ * @st_usage: the state usage statistics
  */
-static inline void * cpuidle_get_statedata(struct cpuidle_state *state)
+static inline void *cpuidle_get_statedata(struct cpuidle_state_usage *st_usage)
 {
-       return state->driver_data;
+       return st_usage->driver_data;
 }
 
 /**
  * cpuidle_set_statedata - stores private driver state data
- * @state: the state
+ * @st_usage: the state usage statistics
  * @data: the private data
  */
 static inline void
-cpuidle_set_statedata(struct cpuidle_state *state, void *data)
+cpuidle_set_statedata(struct cpuidle_state_usage *st_usage, void *data)
 {
-       state->driver_data = data;
+       st_usage->driver_data = data;
 }
 
 struct cpuidle_state_kobj {
        struct cpuidle_state *state;
+       struct cpuidle_state_usage *state_usage;
        struct completion kobj_unregister;
        struct kobject kobj;
 };
@@ -81,22 +86,17 @@ struct cpuidle_state_kobj {
 struct cpuidle_device {
        unsigned int            registered:1;
        unsigned int            enabled:1;
-       unsigned int            power_specified:1;
        unsigned int            cpu;
 
        int                     last_residency;
        int                     state_count;
-       struct cpuidle_state    states[CPUIDLE_STATE_MAX];
+       struct cpuidle_state_usage      states_usage[CPUIDLE_STATE_MAX];
        struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
-       struct cpuidle_state    *last_state;
 
        struct list_head        device_list;
        struct kobject          kobj;
        struct completion       kobj_unregister;
        void                    *governor_data;
-       struct cpuidle_state    *safe_state;
-
-       int (*prepare)          (struct cpuidle_device *dev);
 };
 
 DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
@@ -120,6 +120,11 @@ static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
 struct cpuidle_driver {
        char                    name[CPUIDLE_NAME_LEN];
        struct module           *owner;
+
+       unsigned int            power_specified:1;
+       struct cpuidle_state    states[CPUIDLE_STATE_MAX];
+       int                     state_count;
+       int                     safe_state_index;
 };
 
 #ifdef CONFIG_CPU_IDLE
@@ -166,11 +171,14 @@ struct cpuidle_governor {
        struct list_head        governor_list;
        unsigned int            rating;
 
-       int  (*enable)          (struct cpuidle_device *dev);
-       void (*disable)         (struct cpuidle_device *dev);
+       int  (*enable)          (struct cpuidle_driver *drv,
+                                       struct cpuidle_device *dev);
+       void (*disable)         (struct cpuidle_driver *drv,
+                                       struct cpuidle_device *dev);
 
-       int  (*select)          (struct cpuidle_device *dev);
-       void (*reflect)         (struct cpuidle_device *dev);
+       int  (*select)          (struct cpuidle_driver *drv,
+                                       struct cpuidle_device *dev);
+       void (*reflect)         (struct cpuidle_device *dev, int index);
 
        struct module           *owner;
 };
index afb94583960c9f0b0c1bc2a896ec747f4422e156..98ce8124b1cc5e5fb2e61fcf89cc8bd3cc0a7e82 100644 (file)
@@ -41,7 +41,7 @@ struct devfreq_dev_status {
        unsigned long total_time;
        unsigned long busy_time;
        unsigned long current_frequency;
-       void *private_date;
+       void *private_data;
 };
 
 /**
index ffbcf95cd97dbb3b7e12f9be778c90f1977a9a1a..3136ede5a1e1bb8434a0e2d52840f84de39647de 100644 (file)
@@ -69,7 +69,7 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
  * @resume:    Called to bring a device on this bus out of sleep mode.
  * @pm:                Power management operations of this bus, callback the specific
  *             device driver's pm-ops.
- * @iommu_ops   IOMMU specific operations for this bus, used to attach IOMMU
+ * @iommu_ops:  IOMMU specific operations for this bus, used to attach IOMMU
  *              driver implementations to a bus and allow the driver to do
  *              bus-specific setup
  * @p:         The private data of the driver core, only the driver core can
@@ -682,6 +682,11 @@ static inline bool device_async_suspend_enabled(struct device *dev)
        return !!dev->power.async_suspend;
 }
 
+static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
+{
+       dev->power.ignore_children = enable;
+}
+
 static inline void device_lock(struct device *dev)
 {
        mutex_lock(&dev->mutex);
index 45f00b61c096ec025dfac142c7aaef501bd449dc..de33de1e205295150efb604dbcf6a56f9b4e91e5 100644 (file)
@@ -1097,10 +1097,12 @@ struct ethtool_ops {
 #define SPEED_1000             1000
 #define SPEED_2500             2500
 #define SPEED_10000            10000
+#define SPEED_UNKNOWN          -1
 
 /* Duplex, half or full. */
 #define DUPLEX_HALF            0x00
 #define DUPLEX_FULL            0x01
+#define DUPLEX_UNKNOWN         0xff
 
 /* Which connector port. */
 #define PORT_TP                        0x00
index 0c4df261af7e6a32d5b5c80633fa6a643e2d6285..e3130220ce3e3ddf7837c64b5fdadb0342f9f690 100644 (file)
@@ -1886,6 +1886,7 @@ extern struct dentry *mount_single(struct file_system_type *fs_type,
 extern struct dentry *mount_nodev(struct file_system_type *fs_type,
        int flags, void *data,
        int (*fill_super)(struct super_block *, void *, int));
+extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path);
 void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
 void kill_anon_super(struct super_block *sb);
index 9de31bc98c8803bc96bac1f0751da3ca695bf8df..6d18f3531f180f401d35e8028b3395b339182c2e 100644 (file)
@@ -21,8 +21,6 @@
 #define dev_to_part(device)    container_of((device), struct hd_struct, __dev)
 #define disk_to_dev(disk)      (&(disk)->part0.__dev)
 #define part_to_dev(part)      (&((part)->__dev))
-#define alias_name(disk)       ((disk)->alias ? (disk)->alias : \
-                                                (disk)->disk_name)
 
 extern struct device_type part_type;
 extern struct kobject *block_depr;
@@ -60,7 +58,6 @@ enum {
 
 #define DISK_MAX_PARTS                 256
 #define DISK_NAME_LEN                  32
-#define ALIAS_LEN                      256
 
 #include <linux/major.h>
 #include <linux/device.h>
@@ -166,7 +163,6 @@ struct gendisk {
                                          * disks that can't be partitioned. */
 
        char disk_name[DISK_NAME_LEN];  /* name of major driver */
-       char *alias;                    /* alias name of disk */
        char *(*devnode)(struct gendisk *gd, mode_t *mode);
 
        unsigned int events;            /* supported events */
index 19644e0016bdbb4837e1fa8f28cd276797fd00a4..d9d6c868b86bc01226031d63ce5ee72eb44ebed6 100644 (file)
@@ -110,11 +110,6 @@ static inline void copy_huge_page(struct page *dst, struct page *src)
 
 #define hugetlb_change_protection(vma, address, end, newprot)
 
-#ifndef HPAGE_MASK
-#define HPAGE_MASK     PAGE_MASK               /* Keep the compiler happy */
-#define HPAGE_SIZE     PAGE_SIZE
-#endif
-
 #endif /* !CONFIG_HUGETLB_PAGE */
 
 #define HUGETLB_ANON_FILE "anon_hugepage"
index 08a2fee40659667819d01bc95a184e059d0fd9b1..aad6bd4b3efdf97046edabd3fe75fbb3ed052465 100644 (file)
@@ -118,7 +118,6 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
 static inline
 void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
 {
-       return 0;
 }
 
 static inline int hwspin_lock_get_id(struct hwspinlock *hwlock)
index a81bf6d23b3e6ad62333696032e0b49317115667..07d103a06d64a04e17e06a2b9011f773ef60d8f1 100644 (file)
@@ -432,9 +432,6 @@ void i2c_unlock_adapter(struct i2c_adapter *);
 /* Internal numbers to terminate lists */
 #define I2C_CLIENT_END         0xfffeU
 
-/* The numbers to use to set I2C bus address */
-#define ANY_I2C_BUS            0xffff
-
 /* Construct an I2C_CLIENT_END-terminated array of i2c addresses */
 #define I2C_ADDRS(addr, addrs...) \
        ((const unsigned short []){ addr, ## addrs, I2C_CLIENT_END })
index 80b480c97532f25801c952fef3d515df907b9c8e..abf5028db98193bb36c5a4c590ac588cc2b1b9ca 100644 (file)
@@ -98,9 +98,10 @@ enum {
        INET_DIAG_VEGASINFO,
        INET_DIAG_CONG,
        INET_DIAG_TOS,
+       INET_DIAG_TCLASS,
 };
 
-#define INET_DIAG_MAX INET_DIAG_TOS
+#define INET_DIAG_MAX INET_DIAG_TCLASS
 
 
 /* INET_DIAG_MEM */
index 08ffab01e76c357cc47b378fd07f2895561f6cc3..94b1e356c02ab4fa808b5dd43d1ed9f57afbe50f 100644 (file)
@@ -184,7 +184,6 @@ extern struct cred init_cred;
                [PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),            \
        },                                                              \
        .thread_group   = LIST_HEAD_INIT(tsk.thread_group),             \
-       .dirties = INIT_PROP_LOCAL_SINGLE(dirties),                     \
        INIT_IDS                                                        \
        INIT_PERF_EVENTS(tsk)                                           \
        INIT_TRACE_IRQFLAGS                                             \
index f47fcd30273dd2ce904b6ac0cf11fb963c04826c..c3892fc1d5389c86c664a43ca57bffa0f008d4b8 100644 (file)
@@ -555,7 +555,6 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_PPC_SMT 64
 #define KVM_CAP_PPC_RMA        65
 #define KVM_CAP_MAX_VCPUS 66       /* returns max vcpus per vm */
-#define KVM_CAP_PPC_HIOR 67
 #define KVM_CAP_PPC_PAPR 68
 #define KVM_CAP_S390_GMAP 71
 
index 82b4c8801a4fc673fc4c7c0451bdb11330c821c7..8bf2cb9502dd7ba492680d371279577392c6d3fe 100644 (file)
 
 
 /*Registers VDD1, VDD2 voltage values definitions */
-#define VDD1_2_NUM_VOLTS                               73
+#define VDD1_2_NUM_VOLT_FINE                           73
+#define VDD1_2_NUM_VOLT_COARSE                         3
 #define VDD1_2_MIN_VOLT                                        6000
 #define VDD1_2_OFFSET                                  125
 
index fae295048a8b00e3dbdbd6d8471a8d7c7f728358..83a9caec0e4311e72b3997130d1291030616537f 100644 (file)
 #define WM8958_MICB2_DISCH_SHIFT                     0  /* MICB2_DISCH */
 #define WM8958_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
 
+/*
+ * R210 (0xD2) - Mic Detect 3
+ */
+#define WM8958_MICD_LVL_MASK                    0x07FC  /* MICD_LVL - [10:2] */
+#define WM8958_MICD_LVL_SHIFT                        2  /* MICD_LVL - [10:2] */
+#define WM8958_MICD_LVL_WIDTH                        9  /* MICD_LVL - [10:2] */
+#define WM8958_MICD_VALID                       0x0002  /* MICD_VALID */
+#define WM8958_MICD_VALID_MASK                  0x0002  /* MICD_VALID */
+#define WM8958_MICD_VALID_SHIFT                      1  /* MICD_VALID */
+#define WM8958_MICD_VALID_WIDTH                      1  /* MICD_VALID */
+#define WM8958_MICD_STS                         0x0001  /* MICD_STS */
+#define WM8958_MICD_STS_MASK                    0x0001  /* MICD_STS */
+#define WM8958_MICD_STS_SHIFT                        0  /* MICD_STS */
+#define WM8958_MICD_STS_WIDTH                        1  /* MICD_STS */
+
 /*
  * R76 (0x4C) - Charge Pump (1)
  */
index 57cc0e63714f9651462450db8fbbc78df79b82f1..c4eec228eef9756c660b538018550ab6bfc8790e 100644 (file)
@@ -86,24 +86,39 @@ struct nand_bbt_descr {
 #define NAND_BBT_VERSION       0x00000100
 /* Create a bbt if none exists */
 #define NAND_BBT_CREATE                0x00000200
+/*
+ * Create an empty BBT with no vendor information. Vendor's information may be
+ * unavailable, for example, if the NAND controller has a different data and OOB
+ * layout or if this information is already purged. Must be used in conjunction
+ * with NAND_BBT_CREATE.
+ */
+#define NAND_BBT_CREATE_EMPTY  0x00000400
 /* Search good / bad pattern through all pages of a block */
-#define NAND_BBT_SCANALLPAGES  0x00000400
+#define NAND_BBT_SCANALLPAGES  0x00000800
 /* Scan block empty during good / bad block scan */
-#define NAND_BBT_SCANEMPTY     0x00000800
+#define NAND_BBT_SCANEMPTY     0x00001000
 /* Write bbt if neccecary */
-#define NAND_BBT_WRITE         0x00001000
+#define NAND_BBT_WRITE         0x00002000
 /* Read and write back block contents when writing bbt */
-#define NAND_BBT_SAVECONTENT   0x00002000
+#define NAND_BBT_SAVECONTENT   0x00004000
 /* Search good / bad pattern on the first and the second page */
-#define NAND_BBT_SCAN2NDPAGE   0x00004000
+#define NAND_BBT_SCAN2NDPAGE   0x00008000
 /* Search good / bad pattern on the last page of the eraseblock */
-#define NAND_BBT_SCANLASTPAGE  0x00008000
-/* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */
-#define NAND_BBT_SCANBYTE1AND6 0x00100000
-/* The nand_bbt_descr was created dynamicaly and must be freed */
-#define NAND_BBT_DYNAMICSTRUCT 0x00200000
-/* The bad block table does not OOB for marker */
-#define NAND_BBT_NO_OOB                0x00400000
+#define NAND_BBT_SCANLASTPAGE  0x00010000
+/*
+ * Use a flash based bad block table. By default, OOB identifier is saved in
+ * OOB area. This option is passed to the default bad block table function.
+ */
+#define NAND_BBT_USE_FLASH     0x00020000
+/* Do not store flash based bad block table in OOB area; store it in-band */
+#define NAND_BBT_NO_OOB                0x00040000
+
+/*
+ * Flag set by nand_create_default_bbt_descr(), marking that the nand_bbt_descr
+ * was allocated dynamicaly and must be freed in nand_release(). Has no meaning
+ * in nand_chip.bbt_options.
+ */
+#define NAND_BBT_DYNAMICSTRUCT 0x80000000
 
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS        4
index 37be05bbfbc87a84cf405e762d1c17cfd9f107ff..9f5b312af7838d5275ff9611030da3861ec2d612 100644 (file)
 #define MTD_CHAR_MAJOR 90
 #define MTD_BLOCK_MAJOR 31
 
-#define MTD_ERASE_PENDING              0x01
+#define MTD_ERASE_PENDING      0x01
 #define MTD_ERASING            0x02
 #define MTD_ERASE_SUSPEND      0x04
-#define MTD_ERASE_DONE          0x08
-#define MTD_ERASE_FAILED        0x10
+#define MTD_ERASE_DONE         0x08
+#define MTD_ERASE_FAILED       0x10
 
 #define MTD_FAIL_ADDR_UNKNOWN -1LL
 
-/* If the erase fails, fail_addr might indicate exactly which block failed.  If
-   fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level or was not
-   specific to any particular block. */
+/*
+ * If the erase fails, fail_addr might indicate exactly which block failed. If
+ * fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level
+ * or was not specific to any particular block.
+ */
 struct erase_info {
        struct mtd_info *mtd;
        uint64_t addr;
@@ -59,26 +61,12 @@ struct erase_info {
 };
 
 struct mtd_erase_region_info {
-       uint64_t offset;                        /* At which this region starts, from the beginning of the MTD */
+       uint64_t offset;                /* At which this region starts, from the beginning of the MTD */
        uint32_t erasesize;             /* For this region */
        uint32_t numblocks;             /* Number of blocks of erasesize in this region */
        unsigned long *lockmap;         /* If keeping bitmap of locks */
 };
 
-/*
- * oob operation modes
- *
- * MTD_OOB_PLACE:      oob data are placed at the given offset
- * MTD_OOB_AUTO:       oob data are automatically placed at the free areas
- *                     which are defined by the ecclayout
- * MTD_OOB_RAW:                mode to read oob and data without doing ECC checking
- */
-typedef enum {
-       MTD_OOB_PLACE,
-       MTD_OOB_AUTO,
-       MTD_OOB_RAW,
-} mtd_oob_mode_t;
-
 /**
  * struct mtd_oob_ops - oob operation operands
  * @mode:      operation mode
@@ -90,7 +78,7 @@ typedef enum {
  * @ooblen:    number of oob bytes to write/read
  * @oobretlen: number of oob bytes written/read
  * @ooboffs:   offset of oob data in the oob area (only relevant when
- *             mode = MTD_OOB_PLACE)
+ *             mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW)
  * @datbuf:    data buffer - if NULL only oob data are read/written
  * @oobbuf:    oob data buffer
  *
@@ -99,7 +87,7 @@ typedef enum {
  * OOB area.
  */
 struct mtd_oob_ops {
-       mtd_oob_mode_t  mode;
+       unsigned int    mode;
        size_t          len;
        size_t          retlen;
        size_t          ooblen;
@@ -173,7 +161,7 @@ struct mtd_info {
        const char *name;
        int index;
 
-       /* ecc layout structure pointer - read only ! */
+       /* ECC layout structure pointer - read only! */
        struct nand_ecclayout *ecclayout;
 
        /* Data for variable erase regions. If numeraseregions is zero,
@@ -324,10 +312,15 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
        /* Kernel-side ioctl definitions */
 
 struct mtd_partition;
-
-extern int mtd_device_register(struct mtd_info *master,
-                              const struct mtd_partition *parts,
-                              int nr_parts);
+struct mtd_part_parser_data;
+
+extern int mtd_device_parse_register(struct mtd_info *mtd,
+                             const char **part_probe_types,
+                             struct mtd_part_parser_data *parser_data,
+                             const struct mtd_partition *defparts,
+                             int defnr_parts);
+#define mtd_device_register(master, parts, nr_parts)   \
+       mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
 extern int mtd_device_unregister(struct mtd_info *master);
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern int __get_mtd_device(struct mtd_info *mtd);
@@ -356,27 +349,16 @@ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
 
 void mtd_erase_callback(struct erase_info *instr);
 
-/*
- * Debugging macro and defines
- */
-#define MTD_DEBUG_LEVEL0       (0)     /* Quiet   */
-#define MTD_DEBUG_LEVEL1       (1)     /* Audible */
-#define MTD_DEBUG_LEVEL2       (2)     /* Loud    */
-#define MTD_DEBUG_LEVEL3       (3)     /* Noisy   */
-
-#ifdef CONFIG_MTD_DEBUG
-#define DEBUG(n, args...)                              \
-       do {                                            \
-               if (n <= CONFIG_MTD_DEBUG_VERBOSE)      \
-                       printk(KERN_INFO args);         \
-       } while(0)
-#else /* CONFIG_MTD_DEBUG */
-#define DEBUG(n, args...)                              \
-       do {                                            \
-               if (0)                                  \
-                       printk(KERN_INFO args);         \
-       } while(0)
-
-#endif /* CONFIG_MTD_DEBUG */
+static inline int mtd_is_bitflip(int err) {
+       return err == -EUCLEAN;
+}
+
+static inline int mtd_is_eccerr(int err) {
+       return err == -EBADMSG;
+}
+
+static inline int mtd_is_bitflip_or_eccerr(int err) {
+       return mtd_is_bitflip(err) || mtd_is_eccerr(err);
+}
 
 #endif /* __MTD_MTD_H__ */
index c2b9ac4fbc4ab588074acd2d77f2ad20bc1bddb6..904131bab501380e9a82dbfdafa412609531b7f1 100644 (file)
@@ -42,10 +42,10 @@ extern void nand_release(struct mtd_info *mtd);
 /* Internal helper for board drivers which need to override command function */
 extern void nand_wait_ready(struct mtd_info *mtd);
 
-/* locks all blockes present in the device */
+/* locks all blocks present in the device */
 extern int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 
-/* unlocks specified locked blockes */
+/* unlocks specified locked blocks */
 extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 
 /* The maximum number of NAND chips in an array */
@@ -150,7 +150,7 @@ typedef enum {
 #define NAND_ECC_READ          0
 /* Reset Hardware ECC for write */
 #define NAND_ECC_WRITE         1
-/* Enable Hardware ECC before syndrom is read back from flash */
+/* Enable Hardware ECC before syndrome is read back from flash */
 #define NAND_ECC_READSYN       2
 
 /* Bit mask for flags passed to do_nand_read_ecc */
@@ -163,7 +163,7 @@ typedef enum {
  */
 /* Chip can not auto increment pages */
 #define NAND_NO_AUTOINCR       0x00000001
-/* Buswitdh is 16 bit */
+/* Buswidth is 16 bit */
 #define NAND_BUSWIDTH_16       0x00000002
 /* Device supports partial programming without padding */
 #define NAND_NO_PADDING                0x00000004
@@ -219,27 +219,15 @@ typedef enum {
 #define NAND_CHIPOPTIONS_MSK   (0x0000ffff & ~NAND_NO_AUTOINCR)
 
 /* Non chip related options */
-/*
- * Use a flash based bad block table. OOB identifier is saved in OOB area.
- * This option is passed to the default bad block table function.
- */
-#define NAND_USE_FLASH_BBT     0x00010000
 /* This option skips the bbt scan during initialization. */
-#define NAND_SKIP_BBTSCAN      0x00020000
+#define NAND_SKIP_BBTSCAN      0x00010000
 /*
  * This option is defined if the board driver allocates its own buffers
  * (e.g. because it needs them DMA-coherent).
  */
-#define NAND_OWN_BUFFERS       0x00040000
+#define NAND_OWN_BUFFERS       0x00020000
 /* Chip may not exist, so silence any errors in scan */
-#define NAND_SCAN_SILENT_NODEV 0x00080000
-/*
- * If passed additionally to NAND_USE_FLASH_BBT then BBT code will not touch
- * the OOB area.
- */
-#define NAND_USE_FLASH_BBT_NO_OOB      0x00800000
-/* Create an empty BBT with no vendor information if the BBT is available */
-#define NAND_CREATE_EMPTY_BBT          0x01000000
+#define NAND_SCAN_SILENT_NODEV 0x00040000
 
 /* Options set by nand scan */
 /* Nand scan has allocated controller struct */
@@ -331,27 +319,29 @@ struct nand_hw_control {
 };
 
 /**
- * struct nand_ecc_ctrl - Control structure for ecc
- * @mode:      ecc mode
- * @steps:     number of ecc steps per page
- * @size:      data bytes per ecc step
- * @bytes:     ecc bytes per step
- * @total:     total number of ecc bytes per page
- * @prepad:    padding information for syndrome based ecc generators
- * @postpad:   padding information for syndrome based ecc generators
+ * struct nand_ecc_ctrl - Control structure for ECC
+ * @mode:      ECC mode
+ * @steps:     number of ECC steps per page
+ * @size:      data bytes per ECC step
+ * @bytes:     ECC bytes per step
+ * @total:     total number of ECC bytes per page
+ * @prepad:    padding information for syndrome based ECC generators
+ * @postpad:   padding information for syndrome based ECC generators
  * @layout:    ECC layout control struct pointer
- * @priv:      pointer to private ecc control data
- * @hwctl:     function to control hardware ecc generator. Must only
+ * @priv:      pointer to private ECC control data
+ * @hwctl:     function to control hardware ECC generator. Must only
  *             be provided if an hardware ECC is available
- * @calculate: function for ecc calculation or readback from ecc hardware
- * @correct:   function for ecc correction, matching to ecc generator (sw/hw)
+ * @calculate: function for ECC calculation or readback from ECC hardware
+ * @correct:   function for ECC correction, matching to ECC generator (sw/hw)
  * @read_page_raw:     function to read a raw page without ECC
  * @write_page_raw:    function to write a raw page without ECC
- * @read_page: function to read a page according to the ecc generator
+ * @read_page: function to read a page according to the ECC generator
  *             requirements.
  * @read_subpage:      function to read parts of the page covered by ECC.
- * @write_page:        function to write a page according to the ecc generator
+ * @write_page:        function to write a page according to the ECC generator
  *             requirements.
+ * @write_oob_raw:     function to write chip OOB data without ECC
+ * @read_oob_raw:      function to read chip OOB data without ECC
  * @read_oob:  function to read chip OOB data
  * @write_oob: function to write chip OOB data
  */
@@ -380,6 +370,10 @@ struct nand_ecc_ctrl {
                        uint32_t offs, uint32_t len, uint8_t *buf);
        void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
                        const uint8_t *buf);
+       int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
+                       int page);
+       int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
+                       int page, int sndcmd);
        int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page,
                        int sndcmd);
        int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip,
@@ -388,8 +382,8 @@ struct nand_ecc_ctrl {
 
 /**
  * struct nand_buffers - buffer structure for read/write
- * @ecccalc:   buffer for calculated ecc
- * @ecccode:   buffer for ecc read from flash
+ * @ecccalc:   buffer for calculated ECC
+ * @ecccode:   buffer for ECC read from flash
  * @databuf:   buffer for data - dynamically sized
  *
  * Do not change the order of buffers. databuf and oobrbuf must be in
@@ -422,7 +416,7 @@ struct nand_buffers {
  *                     mtd->oobsize, mtd->writesize and so on.
  *                     @id_data contains the 8 bytes values of NAND_CMD_READID.
  *                     Return with the bus width.
- * @dev_ready:         [BOARDSPECIFIC] hardwarespecific function for accesing
+ * @dev_ready:         [BOARDSPECIFIC] hardwarespecific function for accessing
  *                     device ready/busy line. If set to NULL no access to
  *                     ready/busy is available and the ready/busy information
  *                     is read from the chip status register.
@@ -430,17 +424,17 @@ struct nand_buffers {
  *                     commands to the chip.
  * @waitfunc:          [REPLACEABLE] hardwarespecific function for wait on
  *                     ready.
- * @ecc:               [BOARDSPECIFIC] ecc control ctructure
+ * @ecc:               [BOARDSPECIFIC] ECC control structure
  * @buffers:           buffer structure for read/write
  * @hwcontrol:         platform-specific hardware control structure
- * @ops:               oob operation operands
  * @erase_cmd:         [INTERN] erase command write function, selectable due
  *                     to AND support.
  * @scan_bbt:          [REPLACEABLE] function to scan bad block table
  * @chip_delay:                [BOARDSPECIFIC] chip dependent delay for transferring
  *                     data from array to read regs (tR).
  * @state:             [INTERN] the current state of the NAND device
- * @oob_poi:           poison value buffer
+ * @oob_poi:           "poison value buffer," used for laying out OOB data
+ *                     before writing
  * @page_shift:                [INTERN] number of address bits in a page (column
  *                     address bits).
  * @phys_erase_shift:  [INTERN] number of address bits in a physical eraseblock
@@ -449,6 +443,9 @@ struct nand_buffers {
  * @options:           [BOARDSPECIFIC] various chip options. They can partly
  *                     be set to inform nand_scan about special functionality.
  *                     See the defines for further explanation.
+ * @bbt_options:       [INTERN] bad block specific options. All options used
+ *                     here must come from bbm.h. By default, these options
+ *                     will be copied to the appropriate nand_bbt_descr's.
  * @badblockpos:       [INTERN] position of the bad block marker in the oob
  *                     area.
  * @badblockbits:      [INTERN] number of bits to left-shift the bad block
@@ -464,7 +461,7 @@ struct nand_buffers {
  *                     non 0 if ONFI supported.
  * @onfi_params:       [INTERN] holds the ONFI page parameter when ONFI is
  *                     supported, 0 otherwise.
- * @ecclayout:         [REPLACEABLE] the default ecc placement scheme
+ * @ecclayout:         [REPLACEABLE] the default ECC placement scheme
  * @bbt:               [INTERN] bad block table pointer
  * @bbt_td:            [REPLACEABLE] bad block table descriptor for flash
  *                     lookup.
@@ -472,9 +469,9 @@ struct nand_buffers {
  * @badblock_pattern:  [REPLACEABLE] bad block scan pattern used for initial
  *                     bad block scan.
  * @controller:                [REPLACEABLE] a pointer to a hardware controller
- *                     structure which is shared among multiple independend
+ *                     structure which is shared among multiple independent
  *                     devices.
- * @priv:              [OPTIONAL] pointer to private chip date
+ * @priv:              [OPTIONAL] pointer to private chip data
  * @errstat:           [OPTIONAL] hardware specific function to perform
  *                     additional error status checks (determine if errors are
  *                     correctable).
@@ -509,6 +506,7 @@ struct nand_chip {
 
        int chip_delay;
        unsigned int options;
+       unsigned int bbt_options;
 
        int page_shift;
        int phys_erase_shift;
@@ -536,8 +534,6 @@ struct nand_chip {
        struct nand_buffers *buffers;
        struct nand_hw_control hwcontrol;
 
-       struct mtd_oob_ops ops;
-
        uint8_t *bbt;
        struct nand_bbt_descr *bbt_td;
        struct nand_bbt_descr *bbt_md;
@@ -611,10 +607,9 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
  * @partitions:                mtd partition list
  * @chip_delay:                R/B delay value in us
  * @options:           Option flags, e.g. 16bit buswidth
- * @ecclayout:         ecc layout info structure
+ * @bbt_options:       BBT option flags, e.g. NAND_BBT_USE_FLASH
+ * @ecclayout:         ECC layout info structure
  * @part_probe_types:  NULL-terminated array of probe types
- * @set_parts:         platform specific function to set partitions
- * @priv:              hardware controller specific settings
  */
 struct platform_nand_chip {
        int nr_chips;
@@ -624,9 +619,8 @@ struct platform_nand_chip {
        struct nand_ecclayout *ecclayout;
        int chip_delay;
        unsigned int options;
+       unsigned int bbt_options;
        const char **part_probe_types;
-       void (*set_parts)(uint64_t size, struct platform_nand_chip *chip);
-       void *priv;
 };
 
 /* Keep gcc happy */
index 52b6f187bf49bfdc3038dff70f3117eb4e9a1a97..4596503c9da9e0952d4953fa856572898aabc9be 100644 (file)
@@ -184,6 +184,9 @@ struct onenand_chip {
 #define ONENAND_IS_CACHE_PROGRAM(this)                                 \
        (this->options & ONENAND_HAS_CACHE_PROGRAM)
 
+#define ONENAND_IS_NOP_1(this)                                         \
+       (this->options & ONENAND_HAS_NOP_1)
+
 /* Check byte access in OneNAND */
 #define ONENAND_CHECK_BYTE_ACCESS(addr)                (addr & 0x1)
 
@@ -195,6 +198,7 @@ struct onenand_chip {
 #define ONENAND_HAS_2PLANE             (0x0004)
 #define ONENAND_HAS_4KB_PAGE           (0x0008)
 #define ONENAND_HAS_CACHE_PROGRAM      (0x0010)
+#define ONENAND_HAS_NOP_1              (0x0020)
 #define ONENAND_SKIP_UNLOCK_CHECK      (0x0100)
 #define ONENAND_PAGEBUF_ALLOC          (0x1000)
 #define ONENAND_OOBBUF_ALLOC           (0x2000)
index 3a6f0372fc9658f267fabdf61190b9a32ed4d7e3..2475228c1158e6f54e4f7ce02b2607ee9f487922 100644 (file)
@@ -24,7 +24,9 @@
  *     will extend to the end of the master MTD device.
  * offset: absolute starting position within the master MTD device; if
  *     defined as MTDPART_OFS_APPEND, the partition will start where the
- *     previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
+ *     previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block;
+ *     if MTDPART_OFS_RETAIN, consume as much as possible, leaving size
+ *     after the end of partition.
  * mask_flags: contains flags that have to be masked (removed) from the
  *     master MTD flag set for the corresponding MTD partition.
  *     For example, to force a read-only partition, simply adding
@@ -42,12 +44,25 @@ struct mtd_partition {
        struct nand_ecclayout *ecclayout;       /* out of band layout for this partition (NAND only) */
 };
 
+#define MTDPART_OFS_RETAIN     (-3)
 #define MTDPART_OFS_NXTBLK     (-2)
 #define MTDPART_OFS_APPEND     (-1)
 #define MTDPART_SIZ_FULL       (0)
 
 
 struct mtd_info;
+struct device_node;
+
+/**
+ * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
+ * @origin: for RedBoot, start address of MTD device
+ * @of_node: for OF parsers, device node containing partitioning information
+ */
+struct mtd_part_parser_data {
+       unsigned long origin;
+       struct device_node *of_node;
+};
+
 
 /*
  * Functions dealing with the various ways of partitioning the space
@@ -57,37 +72,12 @@ struct mtd_part_parser {
        struct list_head list;
        struct module *owner;
        const char *name;
-       int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long);
+       int (*parse_fn)(struct mtd_info *, struct mtd_partition **,
+                       struct mtd_part_parser_data *);
 };
 
 extern int register_mtd_parser(struct mtd_part_parser *parser);
 extern int deregister_mtd_parser(struct mtd_part_parser *parser);
-extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
-                               struct mtd_partition **pparts, unsigned long origin);
-
-#define put_partition_parser(p) do { module_put((p)->owner); } while(0)
-
-struct device;
-struct device_node;
-
-#ifdef CONFIG_MTD_OF_PARTS
-int __devinit of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts);
-#else
-static inline int of_mtd_parse_partitions(struct device *dev,
-                                         struct device_node *node,
-                                         struct mtd_partition **pparts)
-{
-       return 0;
-}
-#endif
-
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static inline int mtd_has_cmdlinepart(void) { return 1; }
-#else
-static inline int mtd_has_cmdlinepart(void) { return 0; }
-#endif
 
 int mtd_is_partition(struct mtd_info *mtd);
 int mtd_add_partition(struct mtd_info *master, char *name,
index e5f21d293c70175f1395c3355b3da5a230ee0d99..04e018160e2b516be1e29c383e983036c31ffef6 100644 (file)
@@ -32,21 +32,4 @@ struct physmap_flash_data {
        struct mtd_partition    *parts;
 };
 
-/*
- * Board needs to specify the exact mapping during their setup time.
- */
-void physmap_configure(unsigned long addr, unsigned long size,
-               int bankwidth, void (*set_vpp)(struct map_info *, int) );
-
-/*
- * Machines that wish to do flash partition may want to call this function in
- * their setup routine.
- *
- *     physmap_set_partitions(mypartitions, num_parts);
- *
- * Note that one can always override this hard-coded partition with
- * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS).
- */
-void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
-
 #endif /* __LINUX_MTD_PHYSMAP__ */
index ab2c6343361ae3e82f242df7880f292c189e442d..92ecf5585facf20511cd865db281d33ea828bdad 100644 (file)
@@ -410,6 +410,9 @@ extern const struct inode_operations nfs_file_inode_operations;
 extern const struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
+#ifdef CONFIG_NFS_V4
+extern const struct file_operations nfs4_file_operations;
+#endif /* CONFIG_NFS_V4 */
 extern const struct address_space_operations nfs_file_aops;
 extern const struct address_space_operations nfs_dir_aops;
 
index c74595ba70947926d2b1a99f4157ca7f485dbd13..2a7c533be5dd8aa2f584fde1faad94c558130d75 100644 (file)
@@ -1192,6 +1192,7 @@ struct nfs_rpc_ops {
        const struct dentry_operations *dentry_ops;
        const struct inode_operations *dir_inode_ops;
        const struct inode_operations *file_inode_ops;
+       const struct file_operations *file_ops;
 
        int     (*getroot) (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fsinfo *);
index e3d0b3890249163881eec330894cdd8bb945295a..7ef68724f0f054f88427d2dbc18c63b962a16394 100644 (file)
@@ -12,7 +12,7 @@ struct pci_ats {
        unsigned int is_enabled:1;      /* Enable bit is set */
 };
 
-#ifdef CONFIG_PCI_IOV
+#ifdef CONFIG_PCI_ATS
 
 extern int pci_enable_ats(struct pci_dev *dev, int ps);
 extern void pci_disable_ats(struct pci_dev *dev);
@@ -29,7 +29,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
        return dev->ats && dev->ats->is_enabled;
 }
 
-#else /* CONFIG_PCI_IOV */
+#else /* CONFIG_PCI_ATS */
 
 static inline int pci_enable_ats(struct pci_dev *dev, int ps)
 {
@@ -50,7 +50,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
        return 0;
 }
 
-#endif /* CONFIG_PCI_IOV */
+#endif /* CONFIG_PCI_ATS */
 
 #ifdef CONFIG_PCI_PRI
 
index 337df0d5d5f7eb2e80410e4e0980afe4ef4ed83a..7cda65b5f79806005af9aada8831f8403a519db7 100644 (file)
@@ -338,7 +338,7 @@ struct pci_dev {
        struct list_head msi_list;
 #endif
        struct pci_vpd *vpd;
-#ifdef CONFIG_PCI_IOV
+#ifdef CONFIG_PCI_ATS
        union {
                struct pci_sriov *sriov;        /* SR-IOV capability related */
                struct pci_dev *physfn; /* the PF this VF is associated with */
index 3fdf251389defffd2a3bed1bfb7e1b97c4185655..172ba70306d1e77a4591a0474ad58c1df9460796 100644 (file)
 
 #define PCI_VENDOR_ID_AZWAVE           0x1a3b
 
+#define PCI_VENDOR_ID_ASMEDIA          0x1b21
+
 #define PCI_VENDOR_ID_TEKRAM           0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290     0xdc29
 
index 3605e947fa90db9258363d5ca638082f9512dfbd..04c011038f32080ff6489c5a8cd11aad4878f571 100644 (file)
@@ -121,6 +121,7 @@ extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
 extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
 #else
 
+struct pinctrl_dev;
 
 /* Sufficiently stupid default function when pinctrl is not in use */
 static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
diff --git a/include/linux/platform_data/macb.h b/include/linux/platform_data/macb.h
new file mode 100644 (file)
index 0000000..e7c748f
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __MACB_PDATA_H__
+#define __MACB_PDATA_H__
+
+struct macb_platform_data {
+       u32             phy_mask;
+       u8              phy_irq_pin;    /* PHY IRQ */
+       u8              is_rmii;        /* using RMII interface? */
+};
+
+#endif /* __MACB_PDATA_H__ */
index f15acb64681351b72c5b1c460bf0174ad2f33749..3f3ed83a9aa52cf69df6fd7a925d521cbca96f6d 100644 (file)
@@ -54,118 +54,145 @@ typedef struct pm_message {
 /**
  * struct dev_pm_ops - device PM callbacks
  *
- * Several driver power state transitions are externally visible, affecting
+ * Several device power state transitions are externally visible, affecting
  * the state of pending I/O queues and (for drivers that touch hardware)
  * interrupts, wakeups, DMA, and other hardware state.  There may also be
- * internal transitions to various low power modes, which are transparent
+ * internal transitions to various low-power modes which are transparent
  * to the rest of the driver stack (such as a driver that's ON gating off
  * clocks which are not in active use).
  *
- * The externally visible transitions are handled with the help of the following
- * callbacks included in this structure:
- *
- * @prepare: Prepare the device for the upcoming transition, but do NOT change
- *     its hardware state.  Prevent new children of the device from being
- *     registered after @prepare() returns (the driver's subsystem and
- *     generally the rest of the kernel is supposed to prevent new calls to the
- *     probe method from being made too once @prepare() has succeeded).  If
- *     @prepare() detects a situation it cannot handle (e.g. registration of a
- *     child already in progress), it may return -EAGAIN, so that the PM core
- *     can execute it once again (e.g. after the new child has been registered)
- *     to recover from the race condition.  This method is executed for all
- *     kinds of suspend transitions and is followed by one of the suspend
- *     callbacks: @suspend(), @freeze(), or @poweroff().
- *     The PM core executes @prepare() for all devices before starting to
- *     execute suspend callbacks for any of them, so drivers may assume all of
- *     the other devices to be present and functional while @prepare() is being
- *     executed.  In particular, it is safe to make GFP_KERNEL memory
- *     allocations from within @prepare().  However, drivers may NOT assume
- *     anything about the availability of the user space at that time and it
- *     is not correct to request firmware from within @prepare() (it's too
- *     late to do that).  [To work around this limitation, drivers may
- *     register suspend and hibernation notifiers that are executed before the
- *     freezing of tasks.]
+ * The externally visible transitions are handled with the help of callbacks
+ * included in this structure in such a way that two levels of callbacks are
+ * involved.  First, the PM core executes callbacks provided by PM domains,
+ * device types, classes and bus types.  They are the subsystem-level callbacks
+ * supposed to execute callbacks provided by device drivers, although they may
+ * choose not to do that.  If the driver callbacks are executed, they have to
+ * collaborate with the subsystem-level callbacks to achieve the goals
+ * appropriate for the given system transition, given transition phase and the
+ * subsystem the device belongs to.
+ *
+ * @prepare: The principal role of this callback is to prevent new children of
+ *     the device from being registered after it has returned (the driver's
+ *     subsystem and generally the rest of the kernel is supposed to prevent
+ *     new calls to the probe method from being made too once @prepare() has
+ *     succeeded).  If @prepare() detects a situation it cannot handle (e.g.
+ *     registration of a child already in progress), it may return -EAGAIN, so
+ *     that the PM core can execute it once again (e.g. after a new child has
+ *     been registered) to recover from the race condition.
+ *     This method is executed for all kinds of suspend transitions and is
+ *     followed by one of the suspend callbacks: @suspend(), @freeze(), or
+ *     @poweroff().  The PM core executes subsystem-level @prepare() for all
+ *     devices before starting to invoke suspend callbacks for any of them, so
+ *     generally devices may be assumed to be functional or to respond to
+ *     runtime resume requests while @prepare() is being executed.  However,
+ *     device drivers may NOT assume anything about the availability of user
+ *     space at that time and it is NOT valid to request firmware from within
+ *     @prepare() (it's too late to do that).  It also is NOT valid to allocate
+ *     substantial amounts of memory from @prepare() in the GFP_KERNEL mode.
+ *     [To work around these limitations, drivers may register suspend and
+ *     hibernation notifiers to be executed before the freezing of tasks.]
  *
  * @complete: Undo the changes made by @prepare().  This method is executed for
  *     all kinds of resume transitions, following one of the resume callbacks:
  *     @resume(), @thaw(), @restore().  Also called if the state transition
- *     fails before the driver's suspend callback (@suspend(), @freeze(),
- *     @poweroff()) can be executed (e.g. if the suspend callback fails for one
+ *     fails before the driver's suspend callback: @suspend(), @freeze() or
+ *     @poweroff(), can be executed (e.g. if the suspend callback fails for one
  *     of the other devices that the PM core has unsuccessfully attempted to
  *     suspend earlier).
- *     The PM core executes @complete() after it has executed the appropriate
- *     resume callback for all devices.
+ *     The PM core executes subsystem-level @complete() after it has executed
+ *     the appropriate resume callbacks for all devices.
  *
  * @suspend: Executed before putting the system into a sleep state in which the
- *     contents of main memory are preserved.  Quiesce the device, put it into
- *     a low power state appropriate for the upcoming system state (such as
- *     PCI_D3hot), and enable wakeup events as appropriate.
+ *     contents of main memory are preserved.  The exact action to perform
+ *     depends on the device's subsystem (PM domain, device type, class or bus
+ *     type), but generally the device must be quiescent after subsystem-level
+ *     @suspend() has returned, so that it doesn't do any I/O or DMA.
+ *     Subsystem-level @suspend() is executed for all devices after invoking
+ *     subsystem-level @prepare() for all of them.
  *
  * @resume: Executed after waking the system up from a sleep state in which the
- *     contents of main memory were preserved.  Put the device into the
- *     appropriate state, according to the information saved in memory by the
- *     preceding @suspend().  The driver starts working again, responding to
- *     hardware events and software requests.  The hardware may have gone
- *     through a power-off reset, or it may have maintained state from the
- *     previous suspend() which the driver may rely on while resuming.  On most
- *     platforms, there are no restrictions on availability of resources like
- *     clocks during @resume().
+ *     contents of main memory were preserved.  The exact action to perform
+ *     depends on the device's subsystem, but generally the driver is expected
+ *     to start working again, responding to hardware events and software
+ *     requests (the device itself may be left in a low-power state, waiting
+ *     for a runtime resume to occur).  The state of the device at the time its
+ *     driver's @resume() callback is run depends on the platform and subsystem
+ *     the device belongs to.  On most platforms, there are no restrictions on
+ *     availability of resources like clocks during @resume().
+ *     Subsystem-level @resume() is executed for all devices after invoking
+ *     subsystem-level @resume_noirq() for all of them.
  *
  * @freeze: Hibernation-specific, executed before creating a hibernation image.
- *     Quiesce operations so that a consistent image can be created, but do NOT
- *     otherwise put the device into a low power device state and do NOT emit
- *     system wakeup events.  Save in main memory the device settings to be
- *     used by @restore() during the subsequent resume from hibernation or by
- *     the subsequent @thaw(), if the creation of the image or the restoration
- *     of main memory contents from it fails.
+ *     Analogous to @suspend(), but it should not enable the device to signal
+ *     wakeup events or change its power state.  The majority of subsystems
+ *     (with the notable exception of the PCI bus type) expect the driver-level
+ *     @freeze() to save the device settings in memory to be used by @restore()
+ *     during the subsequent resume from hibernation.
+ *     Subsystem-level @freeze() is executed for all devices after invoking
+ *     subsystem-level @prepare() for all of them.
  *
  * @thaw: Hibernation-specific, executed after creating a hibernation image OR
- *     if the creation of the image fails.  Also executed after a failing
+ *     if the creation of an image has failed.  Also executed after a failing
  *     attempt to restore the contents of main memory from such an image.
  *     Undo the changes made by the preceding @freeze(), so the device can be
  *     operated in the same way as immediately before the call to @freeze().
+ *     Subsystem-level @thaw() is executed for all devices after invoking
+ *     subsystem-level @thaw_noirq() for all of them.  It also may be executed
+ *     directly after @freeze() in case of a transition error.
  *
  * @poweroff: Hibernation-specific, executed after saving a hibernation image.
- *     Quiesce the device, put it into a low power state appropriate for the
- *     upcoming system state (such as PCI_D3hot), and enable wakeup events as
- *     appropriate.
+ *     Analogous to @suspend(), but it need not save the device's settings in
+ *     memory.
+ *     Subsystem-level @poweroff() is executed for all devices after invoking
+ *     subsystem-level @prepare() for all of them.
  *
  * @restore: Hibernation-specific, executed after restoring the contents of main
- *     memory from a hibernation image.  Driver starts working again,
- *     responding to hardware events and software requests.  Drivers may NOT
- *     make ANY assumptions about the hardware state right prior to @restore().
- *     On most platforms, there are no restrictions on availability of
- *     resources like clocks during @restore().
- *
- * @suspend_noirq: Complete the operations of ->suspend() by carrying out any
- *     actions required for suspending the device that need interrupts to be
- *     disabled
- *
- * @resume_noirq: Prepare for the execution of ->resume() by carrying out any
- *     actions required for resuming the device that need interrupts to be
- *     disabled
- *
- * @freeze_noirq: Complete the operations of ->freeze() by carrying out any
- *     actions required for freezing the device that need interrupts to be
- *     disabled
- *
- * @thaw_noirq: Prepare for the execution of ->thaw() by carrying out any
- *     actions required for thawing the device that need interrupts to be
- *     disabled
- *
- * @poweroff_noirq: Complete the operations of ->poweroff() by carrying out any
- *     actions required for handling the device that need interrupts to be
- *     disabled
- *
- * @restore_noirq: Prepare for the execution of ->restore() by carrying out any
- *     actions required for restoring the operations of the device that need
- *     interrupts to be disabled
+ *     memory from a hibernation image, analogous to @resume().
+ *
+ * @suspend_noirq: Complete the actions started by @suspend().  Carry out any
+ *     additional operations required for suspending the device that might be
+ *     racing with its driver's interrupt handler, which is guaranteed not to
+ *     run while @suspend_noirq() is being executed.
+ *     It generally is expected that the device will be in a low-power state
+ *     (appropriate for the target system sleep state) after subsystem-level
+ *     @suspend_noirq() has returned successfully.  If the device can generate
+ *     system wakeup signals and is enabled to wake up the system, it should be
+ *     configured to do so at that time.  However, depending on the platform
+ *     and device's subsystem, @suspend() may be allowed to put the device into
+ *     the low-power state and configure it to generate wakeup signals, in
+ *     which case it generally is not necessary to define @suspend_noirq().
+ *
+ * @resume_noirq: Prepare for the execution of @resume() by carrying out any
+ *     operations required for resuming the device that might be racing with
+ *     its driver's interrupt handler, which is guaranteed not to run while
+ *     @resume_noirq() is being executed.
+ *
+ * @freeze_noirq: Complete the actions started by @freeze().  Carry out any
+ *     additional operations required for freezing the device that might be
+ *     racing with its driver's interrupt handler, which is guaranteed not to
+ *     run while @freeze_noirq() is being executed.
+ *     The power state of the device should not be changed by either @freeze()
+ *     or @freeze_noirq() and it should not be configured to signal system
+ *     wakeup by any of these callbacks.
+ *
+ * @thaw_noirq: Prepare for the execution of @thaw() by carrying out any
+ *     operations required for thawing the device that might be racing with its
+ *     driver's interrupt handler, which is guaranteed not to run while
+ *     @thaw_noirq() is being executed.
+ *
+ * @poweroff_noirq: Complete the actions started by @poweroff().  Analogous to
+ *     @suspend_noirq(), but it need not save the device's settings in memory.
+ *
+ * @restore_noirq: Prepare for the execution of @restore() by carrying out any
+ *     operations required for thawing the device that might be racing with its
+ *     driver's interrupt handler, which is guaranteed not to run while
+ *     @restore_noirq() is being executed.  Analogous to @resume_noirq().
  *
  * All of the above callbacks, except for @complete(), return error codes.
  * However, the error codes returned by the resume operations, @resume(),
- * @thaw(), @restore(), @resume_noirq(), @thaw_noirq(), and @restore_noirq() do
+ * @thaw(), @restore(), @resume_noirq(), @thaw_noirq(), and @restore_noirq(), do
  * not cause the PM core to abort the resume transition during which they are
- * returned.  The error codes returned in that cases are only printed by the PM
+ * returned.  The error codes returned in those cases are only printed by the PM
  * core to the system logs for debugging purposes.  Still, it is recommended
  * that drivers only return error codes from their resume methods in case of an
  * unrecoverable failure (i.e. when the device being handled refuses to resume
@@ -174,31 +201,43 @@ typedef struct pm_message {
  * their children.
  *
  * It is allowed to unregister devices while the above callbacks are being
- * executed.  However, it is not allowed to unregister a device from within any
- * of its own callbacks.
+ * executed.  However, a callback routine must NOT try to unregister the device
+ * it was called for, although it may unregister children of that device (for
+ * example, if it detects that a child was unplugged while the system was
+ * asleep).
+ *
+ * Refer to Documentation/power/devices.txt for more information about the role
+ * of the above callbacks in the system suspend process.
  *
- * There also are the following callbacks related to run-time power management
- * of devices:
+ * There also are callbacks related to runtime power management of devices.
+ * Again, these callbacks are executed by the PM core only for subsystems
+ * (PM domains, device types, classes and bus types) and the subsystem-level
+ * callbacks are supposed to invoke the driver callbacks.  Moreover, the exact
+ * actions to be performed by a device driver's callbacks generally depend on
+ * the platform and subsystem the device belongs to.
  *
  * @runtime_suspend: Prepare the device for a condition in which it won't be
  *     able to communicate with the CPU(s) and RAM due to power management.
- *     This need not mean that the device should be put into a low power state.
+ *     This need not mean that the device should be put into a low-power state.
  *     For example, if the device is behind a link which is about to be turned
  *     off, the device may remain at full power.  If the device does go to low
- *     power and is capable of generating run-time wake-up events, remote
- *     wake-up (i.e., a hardware mechanism allowing the device to request a
- *     change of its power state via a wake-up event, such as PCI PME) should
- *     be enabled for it.
+ *     power and is capable of generating runtime wakeup events, remote wakeup
+ *     (i.e., a hardware mechanism allowing the device to request a change of
+ *     its power state via an interrupt) should be enabled for it.
  *
  * @runtime_resume: Put the device into the fully active state in response to a
- *     wake-up event generated by hardware or at the request of software.  If
- *     necessary, put the device into the full power state and restore its
+ *     wakeup event generated by hardware or at the request of software.  If
+ *     necessary, put the device into the full-power state and restore its
  *     registers, so that it is fully operational.
  *
- * @runtime_idle: Device appears to be inactive and it might be put into a low
- *     power state if all of the necessary conditions are satisfied.  Check
+ * @runtime_idle: Device appears to be inactive and it might be put into a
+ *     low-power state if all of the necessary conditions are satisfied.  Check
  *     these conditions and handle the device as appropriate, possibly queueing
  *     a suspend request for it.  The return value is ignored by the PM core.
+ *
+ * Refer to Documentation/power/runtime_pm.txt for more information about the
+ * role of the above callbacks in device runtime power management.
+ *
  */
 
 struct dev_pm_ops {
@@ -447,6 +486,7 @@ struct dev_pm_info {
        unsigned int            async_suspend:1;
        bool                    is_prepared:1;  /* Owned by the PM core */
        bool                    is_suspended:1; /* Ditto */
+       bool                    ignore_children:1;
        spinlock_t              lock;
 #ifdef CONFIG_PM_SLEEP
        struct list_head        entry;
@@ -464,7 +504,6 @@ struct dev_pm_info {
        atomic_t                usage_count;
        atomic_t                child_count;
        unsigned int            disable_depth:3;
-       unsigned int            ignore_children:1;
        unsigned int            idle_notification:1;
        unsigned int            request_pending:1;
        unsigned int            deferred_resume:1;
index d8d90361964216f771ed62e5d17fb083451e2796..d3085e72a0ee9b43bbd024bf33b93939e1535d42 100644 (file)
@@ -52,11 +52,6 @@ static inline bool pm_children_suspended(struct device *dev)
                || !atomic_read(&dev->power.child_count);
 }
 
-static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
-{
-       dev->power.ignore_children = enable;
-}
-
 static inline void pm_runtime_get_noresume(struct device *dev)
 {
        atomic_inc(&dev->power.usage_count);
@@ -130,7 +125,6 @@ static inline void pm_runtime_allow(struct device *dev) {}
 static inline void pm_runtime_forbid(struct device *dev) {}
 
 static inline bool pm_children_suspended(struct device *dev) { return false; }
-static inline void pm_suspend_ignore_children(struct device *dev, bool en) {}
 static inline void pm_runtime_get_noresume(struct device *dev) {}
 static inline void pm_runtime_put_noidle(struct device *dev) {}
 static inline bool device_run_wake(struct device *dev) { return false; }
index ea567321ae3c3b2ac02967680f99de1687f99982..2ca8cde5459d3445b2897c02d58ac2d12dba5bba 100644 (file)
@@ -35,10 +35,12 @@ struct pstore_info {
        spinlock_t      buf_lock;       /* serialize access to 'buf' */
        char            *buf;
        size_t          bufsize;
+       struct mutex    read_mutex;     /* serialize open/read/close */
        int             (*open)(struct pstore_info *psi);
        int             (*close)(struct pstore_info *psi);
        ssize_t         (*read)(u64 *id, enum pstore_type_id *type,
-                       struct timespec *time, struct pstore_info *psi);
+                       struct timespec *time, char **buf,
+                       struct pstore_info *psi);
        int             (*write)(enum pstore_type_id type, u64 *id,
                        unsigned int part, size_t size, struct pstore_info *psi);
        int             (*erase)(enum pstore_type_id type, u64 id,
index 68daf4f27e2c337102258d71450eabc5a14178dd..1c4f3e9b9bc50e52ea57623f5b886691fb52db14 100644 (file)
@@ -1521,7 +1521,6 @@ struct task_struct {
 #ifdef CONFIG_FAULT_INJECTION
        int make_it_fail;
 #endif
-       struct prop_local_single dirties;
        /*
         * when (nr_dirtied >= nr_dirtied_pause), it's time to call
         * balance_dirty_pages() for some dirty throttling pause
index 97ff8e27a6cccfdc0678211db90b1fcde056f1da..3d86517fe7d5bf71f16efa468cec3fb9b4485c17 100644 (file)
@@ -207,13 +207,15 @@ struct serial_icounter_struct {
 
 struct serial_rs485 {
        __u32   flags;                  /* RS485 feature flags */
-#define SER_RS485_ENABLED              (1 << 0)
-#define SER_RS485_RTS_ON_SEND          (1 << 1)
-#define SER_RS485_RTS_AFTER_SEND       (1 << 2)
-#define SER_RS485_RTS_BEFORE_SEND      (1 << 3)
+#define SER_RS485_ENABLED              (1 << 0)        /* If enabled */
+#define SER_RS485_RTS_ON_SEND          (1 << 1)        /* Logical level for
+                                                          RTS pin when
+                                                          sending */
+#define SER_RS485_RTS_AFTER_SEND       (1 << 2)        /* Logical level for
+                                                          RTS pin after sent*/
 #define SER_RS485_RX_DURING_TX         (1 << 4)
-       __u32   delay_rts_before_send;  /* Milliseconds */
-       __u32   delay_rts_after_send;   /* Milliseconds */
+       __u32   delay_rts_before_send;  /* Delay before send (milliseconds) */
+       __u32   delay_rts_after_send;   /* Delay after send (milliseconds) */
        __u32   padding[5];             /* Memory is cheap, new structs
                                           are a royal PITA .. */
 };
index 0efa1f10bc2b35a844b2f3b62589b5269a30b889..369273a5267908791efc203537e0f349edaef0cf 100644 (file)
@@ -67,6 +67,7 @@ enum {
        SCIx_IRDA_REGTYPE,
        SCIx_SCIFA_REGTYPE,
        SCIx_SCIFB_REGTYPE,
+       SCIx_SH2_SCIF_FIFODATA_REGTYPE,
        SCIx_SH3_SCIF_REGTYPE,
        SCIx_SH4_SCIF_REGTYPE,
        SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
index 3ccf18648d0ae885d5421695b45b8b16b2856f61..a20831cf336a5ef5f6cc427b6b131766a34ca761 100644 (file)
@@ -52,7 +52,6 @@ struct clk {
 
        unsigned long           arch_flags;
        void                    *priv;
-       struct dentry           *dentry;
        struct clk_mapping      *mapping;
        struct cpufreq_frequency_table *freq_table;
        unsigned int            nr_freqs;
@@ -94,6 +93,9 @@ int clk_rate_table_find(struct clk *clk,
 long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
                              unsigned int div_max, unsigned long rate);
 
+long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min,
+                              unsigned int mult_max, unsigned long rate);
+
 long clk_round_parent(struct clk *clk, unsigned long target,
                      unsigned long *best_freq, unsigned long *parent_freq,
                      unsigned int div_min, unsigned int div_max);
index bc8c9208f7e21c455fcc4463601ec217de6ec4da..8446789216e568008fb71e9c85189758bf0197a4 100644 (file)
@@ -104,4 +104,80 @@ struct pinmux_info {
 int register_pinmux(struct pinmux_info *pip);
 int unregister_pinmux(struct pinmux_info *pip);
 
+/* helper macro for port */
+#define PORT_1(fn, pfx, sfx) fn(pfx, sfx)
+
+#define PORT_10(fn, pfx, sfx) \
+       PORT_1(fn, pfx##0, sfx), PORT_1(fn, pfx##1, sfx),       \
+       PORT_1(fn, pfx##2, sfx), PORT_1(fn, pfx##3, sfx),       \
+       PORT_1(fn, pfx##4, sfx), PORT_1(fn, pfx##5, sfx),       \
+       PORT_1(fn, pfx##6, sfx), PORT_1(fn, pfx##7, sfx),       \
+       PORT_1(fn, pfx##8, sfx), PORT_1(fn, pfx##9, sfx)
+
+#define PORT_90(fn, pfx, sfx) \
+       PORT_10(fn, pfx##1, sfx), PORT_10(fn, pfx##2, sfx),     \
+       PORT_10(fn, pfx##3, sfx), PORT_10(fn, pfx##4, sfx),     \
+       PORT_10(fn, pfx##5, sfx), PORT_10(fn, pfx##6, sfx),     \
+       PORT_10(fn, pfx##7, sfx), PORT_10(fn, pfx##8, sfx),     \
+       PORT_10(fn, pfx##9, sfx)
+
+#define _PORT_ALL(pfx, sfx) pfx##_##sfx
+#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
+#define PORT_ALL(str)  CPU_ALL_PORT(_PORT_ALL, PORT, str)
+#define GPIO_PORT_ALL()        CPU_ALL_PORT(_GPIO_PORT, , unused)
+#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
+
+/* helper macro for pinmux_enum_t */
+#define PORT_DATA_I(nr)        \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
+
+#define PORT_DATA_I_PD(nr)     \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PD)
+
+#define PORT_DATA_I_PU(nr)     \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PU)
+
+#define PORT_DATA_I_PU_PD(nr)  \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,                    \
+                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
+
+#define PORT_DATA_O(nr)                \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
+
+#define PORT_DATA_IO(nr)       \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,    \
+                   PORT##nr##_IN)
+
+#define PORT_DATA_IO_PD(nr)    \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PD)
+
+#define PORT_DATA_IO_PU(nr)    \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PU)
+
+#define PORT_DATA_IO_PU_PD(nr) \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
+
+/* helper macro for top 4 bits in PORTnCR */
+#define _PCRH(in, in_pd, in_pu, out)   \
+       0, (out), (in), 0,              \
+       0, 0, 0, 0,                     \
+       0, 0, (in_pd), 0,               \
+       0, 0, (in_pu), 0
+
+#define PORTCR(nr, reg)                                                        \
+       {                                                               \
+               PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {             \
+                       _PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,          \
+                             PORT##nr##_IN_PU, PORT##nr##_OUT),        \
+                               PORT##nr##_FN0, PORT##nr##_FN1,         \
+                               PORT##nr##_FN2, PORT##nr##_FN3,         \
+                               PORT##nr##_FN4, PORT##nr##_FN5,         \
+                               PORT##nr##_FN6, PORT##nr##_FN7 }        \
+       }
+
 #endif /* __SH_PFC_H */
index add4790b21fe4ee18635db9456a43db71bb39997..e9e72bda1b72b89b8f4354b507f7b392291ec0ec 100644 (file)
@@ -85,6 +85,8 @@
  * @reset: reset the device
  *     vdev: the virtio device
  *     After this, status and feature negotiation must be done again
+ *     Device must not be reset from its vq/config callbacks, or in
+ *     parallel with being added/removed.
  * @find_vqs: find virtqueues and instantiate them.
  *     vdev: the virtio_device
  *     nvqs: the number of virtqueues to find
index 27c7edefbc86ea6cad445f3503de9970b1088bf7..5c7b6f0daef8f1f228c6daed124e589acdfdb649 100644 (file)
@@ -63,7 +63,7 @@
 #define VIRTIO_MMIO_GUEST_FEATURES     0x020
 
 /* Activated features set selector - Write Only */
-#define VIRTIO_MMIO_GUEST_FEATURES_SET 0x024
+#define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024
 
 /* Guest's memory page size in bytes - Write Only */
 #define VIRTIO_MMIO_GUEST_PAGE_SIZE    0x028
index 687fb11e20107d9c22467e1923d5e736bde16d3e..4bde182fcf93f23bb8f1b8b68d2a087ba20ae2c3 100644 (file)
@@ -119,7 +119,7 @@ unmap_kernel_range(unsigned long addr, unsigned long size)
 #endif
 
 /* Allocate/destroy a 'vmalloc' VM area. */
-extern struct vm_struct *alloc_vm_area(size_t size);
+extern struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes);
 extern void free_vm_area(struct vm_struct *area);
 
 /* for /dev/kmem */
index 2f7d45bcbd243c1b13e726c726dd887ba0c787d2..1a7e1d20adf9ee657044935a5bfc43874d585bb7 100644 (file)
@@ -45,6 +45,51 @@ struct mtd_oob_buf64 {
        __u64 usr_ptr;
 };
 
+/**
+ * MTD operation modes
+ *
+ * @MTD_OPS_PLACE_OOB: OOB data are placed at the given offset (default)
+ * @MTD_OPS_AUTO_OOB:  OOB data are automatically placed at the free areas
+ *                     which are defined by the internal ecclayout
+ * @MTD_OPS_RAW:       data are transferred as-is, with no error correction;
+ *                     this mode implies %MTD_OPS_PLACE_OOB
+ *
+ * These modes can be passed to ioctl(MEMWRITE) and are also used internally.
+ * See notes on "MTD file modes" for discussion on %MTD_OPS_RAW vs.
+ * %MTD_FILE_MODE_RAW.
+ */
+enum {
+       MTD_OPS_PLACE_OOB = 0,
+       MTD_OPS_AUTO_OOB = 1,
+       MTD_OPS_RAW = 2,
+};
+
+/**
+ * struct mtd_write_req - data structure for requesting a write operation
+ *
+ * @start:     start address
+ * @len:       length of data buffer
+ * @ooblen:    length of OOB buffer
+ * @usr_data:  user-provided data buffer
+ * @usr_oob:   user-provided OOB buffer
+ * @mode:      MTD mode (see "MTD operation modes")
+ * @padding:   reserved, must be set to 0
+ *
+ * This structure supports ioctl(MEMWRITE) operations, allowing data and/or OOB
+ * writes in various modes. To write to OOB-only, set @usr_data == NULL, and to
+ * write data-only, set @usr_oob == NULL. However, setting both @usr_data and
+ * @usr_oob to NULL is not allowed.
+ */
+struct mtd_write_req {
+       __u64 start;
+       __u64 len;
+       __u64 ooblen;
+       __u64 usr_data;
+       __u64 usr_oob;
+       __u8 mode;
+       __u8 padding[7];
+};
+
 #define MTD_ABSENT             0
 #define MTD_RAM                        1
 #define MTD_ROM                        2
@@ -59,13 +104,13 @@ struct mtd_oob_buf64 {
 #define MTD_NO_ERASE           0x1000  /* No erase necessary */
 #define MTD_POWERUP_LOCK       0x2000  /* Always locked after reset */
 
-// Some common devices / combinations of capabilities
+/* Some common devices / combinations of capabilities */
 #define MTD_CAP_ROM            0
 #define MTD_CAP_RAM            (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
 #define MTD_CAP_NORFLASH       (MTD_WRITEABLE | MTD_BIT_WRITEABLE)
 #define MTD_CAP_NANDFLASH      (MTD_WRITEABLE)
 
-/* ECC byte placement */
+/* Obsolete ECC byte placement modes (used with obsolete MEMGETOOBSEL) */
 #define MTD_NANDECC_OFF                0       // Switch off ECC (Not recommended)
 #define MTD_NANDECC_PLACE      1       // Use the given placement in the structure (YAFFS1 legacy mode)
 #define MTD_NANDECC_AUTOPLACE  2       // Use the default placement scheme
@@ -80,21 +125,18 @@ struct mtd_oob_buf64 {
 struct mtd_info_user {
        __u8 type;
        __u32 flags;
-       __u32 size;      // Total size of the MTD
+       __u32 size;     /* Total size of the MTD */
        __u32 erasesize;
        __u32 writesize;
-       __u32 oobsize;   // Amount of OOB data per block (e.g. 16)
-       /* The below two fields are obsolete and broken, do not use them
-        * (TODO: remove at some point) */
-       __u32 ecctype;
-       __u32 eccsize;
+       __u32 oobsize;  /* Amount of OOB data per block (e.g. 16) */
+       __u64 padding;  /* Old obsolete field; do not use */
 };
 
 struct region_info_user {
        __u32 offset;           /* At which this region starts,
-                                        * from the beginning of the MTD */
-       __u32 erasesize;                /* For this region */
-       __u32 numblocks;                /* Number of blocks in this region */
+                                * from the beginning of the MTD */
+       __u32 erasesize;        /* For this region */
+       __u32 numblocks;        /* Number of blocks in this region */
        __u32 regionindex;
 };
 
@@ -104,29 +146,61 @@ struct otp_info {
        __u32 locked;
 };
 
+/*
+ * Note, the following ioctl existed in the past and was removed:
+ * #define MEMSETOOBSEL           _IOW('M', 9, struct nand_oobinfo)
+ * Try to avoid adding a new ioctl with the same ioctl number.
+ */
+
+/* Get basic MTD characteristics info (better to use sysfs) */
 #define MEMGETINFO             _IOR('M', 1, struct mtd_info_user)
+/* Erase segment of MTD */
 #define MEMERASE               _IOW('M', 2, struct erase_info_user)
+/* Write out-of-band data from MTD */
 #define MEMWRITEOOB            _IOWR('M', 3, struct mtd_oob_buf)
+/* Read out-of-band data from MTD */
 #define MEMREADOOB             _IOWR('M', 4, struct mtd_oob_buf)
+/* Lock a chip (for MTD that supports it) */
 #define MEMLOCK                        _IOW('M', 5, struct erase_info_user)
+/* Unlock a chip (for MTD that supports it) */
 #define MEMUNLOCK              _IOW('M', 6, struct erase_info_user)
+/* Get the number of different erase regions */
 #define MEMGETREGIONCOUNT      _IOR('M', 7, int)
+/* Get information about the erase region for a specific index */
 #define MEMGETREGIONINFO       _IOWR('M', 8, struct region_info_user)
-#define MEMSETOOBSEL           _IOW('M', 9, struct nand_oobinfo)
+/* Get info about OOB modes (e.g., RAW, PLACE, AUTO) - legacy interface */
 #define MEMGETOOBSEL           _IOR('M', 10, struct nand_oobinfo)
+/* Check if an eraseblock is bad */
 #define MEMGETBADBLOCK         _IOW('M', 11, __kernel_loff_t)
+/* Mark an eraseblock as bad */
 #define MEMSETBADBLOCK         _IOW('M', 12, __kernel_loff_t)
+/* Set OTP (One-Time Programmable) mode (factory vs. user) */
 #define OTPSELECT              _IOR('M', 13, int)
+/* Get number of OTP (One-Time Programmable) regions */
 #define OTPGETREGIONCOUNT      _IOW('M', 14, int)
+/* Get all OTP (One-Time Programmable) info about MTD */
 #define OTPGETREGIONINFO       _IOW('M', 15, struct otp_info)
+/* Lock a given range of user data (must be in mode %MTD_FILE_MODE_OTP_USER) */
 #define OTPLOCK                        _IOR('M', 16, struct otp_info)
+/* Get ECC layout (deprecated) */
 #define ECCGETLAYOUT           _IOR('M', 17, struct nand_ecclayout_user)
+/* Get statistics about corrected/uncorrected errors */
 #define ECCGETSTATS            _IOR('M', 18, struct mtd_ecc_stats)
+/* Set MTD mode on a per-file-descriptor basis (see "MTD file modes") */
 #define MTDFILEMODE            _IO('M', 19)
+/* Erase segment of MTD (supports 64-bit address) */
 #define MEMERASE64             _IOW('M', 20, struct erase_info_user64)
+/* Write data to OOB (64-bit version) */
 #define MEMWRITEOOB64          _IOWR('M', 21, struct mtd_oob_buf64)
+/* Read data from OOB (64-bit version) */
 #define MEMREADOOB64           _IOWR('M', 22, struct mtd_oob_buf64)
+/* Check if chip is locked (for MTD that supports it) */
 #define MEMISLOCKED            _IOR('M', 23, struct erase_info_user)
+/*
+ * Most generic write interface; can write in-band and/or out-of-band in various
+ * modes (see "struct mtd_write_req")
+ */
+#define MEMWRITE               _IOWR('M', 24, struct mtd_write_req)
 
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
@@ -177,13 +251,27 @@ struct mtd_ecc_stats {
 };
 
 /*
- * Read/write file modes for access to MTD
+ * MTD file modes - for read/write access to MTD
+ *
+ * @MTD_FILE_MODE_NORMAL:      OTP disabled, ECC enabled
+ * @MTD_FILE_MODE_OTP_FACTORY: OTP enabled in factory mode
+ * @MTD_FILE_MODE_OTP_USER:    OTP enabled in user mode
+ * @MTD_FILE_MODE_RAW:         OTP disabled, ECC disabled
+ *
+ * These modes can be set via ioctl(MTDFILEMODE). The mode mode will be retained
+ * separately for each open file descriptor.
+ *
+ * Note: %MTD_FILE_MODE_RAW provides the same functionality as %MTD_OPS_RAW -
+ * raw access to the flash, without error correction or autoplacement schemes.
+ * Wherever possible, the MTD_OPS_* mode will override the MTD_FILE_MODE_* mode
+ * (e.g., when using ioctl(MEMWRITE)), but in some cases, the MTD_FILE_MODE is
+ * used out of necessity (e.g., `write()', ioctl(MEMWRITEOOB64)).
  */
 enum mtd_file_modes {
-       MTD_MODE_NORMAL = MTD_OTP_OFF,
-       MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
-       MTD_MODE_OTP_USER = MTD_OTP_USER,
-       MTD_MODE_RAW,
+       MTD_FILE_MODE_NORMAL = MTD_OTP_OFF,
+       MTD_FILE_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
+       MTD_FILE_MODE_OTP_USER = MTD_OTP_USER,
+       MTD_FILE_MODE_RAW,
 };
 
 #endif /* __MTD_ABI_H__ */
index ab90ae0970a69b2f3646c712aac0b56e2332509e..6cc18f37167519260e15d1ad20d7bf2f145c86c5 100644 (file)
 #define L2CAP_DEFAULT_ACK_TO           200
 #define L2CAP_LE_DEFAULT_MTU           23
 
-#define L2CAP_CONN_TIMEOUT     (40000) /* 40 seconds */
-#define L2CAP_INFO_TIMEOUT     (4000)  /*  4 seconds */
+#define L2CAP_DISC_TIMEOUT             (100)
+#define L2CAP_DISC_REJ_TIMEOUT         (5000)  /*  5 seconds */
+#define L2CAP_ENC_TIMEOUT              (5000)  /*  5 seconds */
+#define L2CAP_CONN_TIMEOUT             (40000) /* 40 seconds */
+#define L2CAP_INFO_TIMEOUT             (4000)  /*  4 seconds */
 
 /* L2CAP socket address */
 struct sockaddr_l2 {
index d5eee2093b1eed75575764d9848655ee90825b80..e2e3ecad100830a6cb42765c65ca804304eb5fca 100644 (file)
@@ -211,6 +211,7 @@ struct rfcomm_dlc {
 #define RFCOMM_AUTH_ACCEPT  6
 #define RFCOMM_AUTH_REJECT  7
 #define RFCOMM_DEFER_SETUP  8
+#define RFCOMM_ENC_DROP     9
 
 /* Scheduling flags and events */
 #define RFCOMM_SCHED_WAKEUP 31
index 92cf1c2c30c9f0a94d193753a037cb851f8a60cd..95852e36713b5e302e365033957d16910de01952 100644 (file)
@@ -456,6 +456,9 @@ enum station_parameters_apply_mask {
  *     as the AC bitmap in the QoS info field
  * @max_sp: max Service Period. same format as the MAX_SP in the
  *     QoS info field (but already shifted down)
+ * @sta_modify_mask: bitmap indicating which parameters changed
+ *     (for those that don't have a natural "no change" value),
+ *     see &enum station_parameters_apply_mask
  */
 struct station_parameters {
        u8 *supported_rates;
@@ -615,6 +618,7 @@ struct sta_bss_parameters {
  *     user space MLME/SME implementation. The information is provided for
  *     the cfg80211_new_sta() calls to notify user space of the IEs.
  * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets.
+ * @sta_flags: station flags mask & values
  */
 struct station_info {
        u32 filled;
index dc1123aa8181d08a9b91bf2fe3281577088e56d1..72eddd1b410b9c8418216c17d74910585fdec975 100644 (file)
@@ -3567,8 +3567,9 @@ rate_lowest_index(struct ieee80211_supported_band *sband,
                        return i;
 
        /* warn when we cannot find a rate. */
-       WARN_ON(1);
+       WARN_ON_ONCE(1);
 
+       /* and return 0 (the lowest index) */
        return 0;
 }
 
index 98c185441bee0c2bf8b36caeb5637b13878cfaff..cb1f3504687fb74df065191ce65add598f063dac 100644 (file)
@@ -192,8 +192,15 @@ enum {
  *    NLA_NUL_STRING       Maximum length of string (excluding NUL)
  *    NLA_FLAG             Unused
  *    NLA_BINARY           Maximum length of attribute payload
- *    NLA_NESTED_COMPAT    Exact length of structure payload
- *    All other            Exact length of attribute payload
+ *    NLA_NESTED           Don't use `len' field -- length verification is
+ *                         done by checking len of nested header (or empty)
+ *    NLA_NESTED_COMPAT    Minimum length of structure payload
+ *    NLA_U8, NLA_U16,
+ *    NLA_U32, NLA_U64,
+ *    NLA_MSECS            Leaving the length field zero will verify the
+ *                         given type fits, using it verifies minimum length
+ *                         just like "All other"
+ *    All other            Minimum length of attribute payload
  *
  * Example:
  * static const struct nla_policy my_policy[ATTR_MAX+1] = {
index d0e0de7984ecb300b160bd6523e70a566d14636f..f22f3e16edf46d082b49849116001f65be8fde73 100644 (file)
@@ -10,7 +10,7 @@
 #define __SOUND_SAIF_H__
 
 struct mxs_saif_platform_data {
-       int (*init) (void);
-       int (*get_master_id) (unsigned int saif_id);
+       bool master_mode;       /* if true use master mode */
+       int master_id;          /* id of the master if in slave mode */
 };
 #endif
index b66ebb2032c6d6b87c928876cab69c235d2425f3..378c7ed6760be0563b501971df2a60e03a672ea7 100644 (file)
@@ -307,15 +307,8 @@ struct omap_dss_board_info {
        void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
 };
 
-#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS)
 /* Init with the board info */
 extern int omap_display_init(struct omap_dss_board_info *board_data);
-#else
-static inline int omap_display_init(struct omap_dss_board_info *board_data)
-{
-       return 0;
-}
-#endif
 
 struct omap_display_platform_data {
        struct omap_dss_board_info *board_data;
index a785a3b0c8c7d89d9a46e1a1d90300cb91da5308..438c256c274b3b7984155399f87e26cd13d27cd7 100644 (file)
@@ -29,8 +29,7 @@
 static inline int xen_must_unplug_nics(void) {
 #if (defined(CONFIG_XEN_NETDEV_FRONTEND) || \
                defined(CONFIG_XEN_NETDEV_FRONTEND_MODULE)) && \
-               (defined(CONFIG_XEN_PLATFORM_PCI) || \
-                defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
+               defined(CONFIG_XEN_PVHVM)
         return 1;
 #else
         return 0;
@@ -40,8 +39,7 @@ static inline int xen_must_unplug_nics(void) {
 static inline int xen_must_unplug_disks(void) {
 #if (defined(CONFIG_XEN_BLKDEV_FRONTEND) || \
                defined(CONFIG_XEN_BLKDEV_FRONTEND_MODULE)) && \
-               (defined(CONFIG_XEN_PLATFORM_PCI) || \
-                defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
+               defined(CONFIG_XEN_PVHVM)
         return 1;
 #else
         return 0;
index 5e828a2ca8e64641749da837fe093cefcfc958dc..213c0351dad8fc8315d6d79a5bf3706a59c823bd 100644 (file)
@@ -153,6 +153,13 @@ static void freezer_destroy(struct cgroup_subsys *ss,
        kfree(cgroup_freezer(cgroup));
 }
 
+/* task is frozen or will freeze immediately when next it gets woken */
+static bool is_task_frozen_enough(struct task_struct *task)
+{
+       return frozen(task) ||
+               (task_is_stopped_or_traced(task) && freezing(task));
+}
+
 /*
  * The call to cgroup_lock() in the freezer.state write method prevents
  * a write to that file racing against an attach, and hence the
@@ -231,7 +238,7 @@ static void update_if_frozen(struct cgroup *cgroup,
        cgroup_iter_start(cgroup, &it);
        while ((task = cgroup_iter_next(cgroup, &it))) {
                ntotal++;
-               if (frozen(task))
+               if (is_task_frozen_enough(task))
                        nfrozen++;
        }
 
@@ -284,7 +291,7 @@ static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
        while ((task = cgroup_iter_next(cgroup, &it))) {
                if (!freeze_task(task, true))
                        continue;
-               if (frozen(task))
+               if (is_task_frozen_enough(task))
                        continue;
                if (!freezing(task) && !freezer_should_skip(task))
                        num_cant_freeze_now++;
index ba0d172613296047a24918106d90eff09f2a5bb8..da4a6a10d088d2d575c4eeae9438f832efc6f41b 100644 (file)
@@ -162,7 +162,6 @@ static void account_kernel_stack(struct thread_info *ti, int account)
 
 void free_task(struct task_struct *tsk)
 {
-       prop_local_destroy_single(&tsk->dirties);
        account_kernel_stack(tsk->stack, -1);
        free_thread_info(tsk->stack);
        rt_mutex_debug_task_free(tsk);
@@ -274,10 +273,6 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 
        tsk->stack = ti;
 
-       err = prop_local_init_single(&tsk->dirties);
-       if (err)
-               goto out;
-
        setup_thread_stack(tsk, orig);
        clear_user_return_notifier(tsk);
        clear_tsk_need_resched(tsk);
index 422e567eecf63636a7c349b6319e6d541c6f3818..ae34bf51682b4a204de93f62943055350cd5c4d0 100644 (file)
@@ -885,10 +885,13 @@ static void __remove_hrtimer(struct hrtimer *timer,
                             struct hrtimer_clock_base *base,
                             unsigned long newstate, int reprogram)
 {
+       struct timerqueue_node *next_timer;
        if (!(timer->state & HRTIMER_STATE_ENQUEUED))
                goto out;
 
-       if (&timer->node == timerqueue_getnext(&base->active)) {
+       next_timer = timerqueue_getnext(&base->active);
+       timerqueue_del(&base->active, &timer->node);
+       if (&timer->node == next_timer) {
 #ifdef CONFIG_HIGH_RES_TIMERS
                /* Reprogram the clock event device. if enabled */
                if (reprogram && hrtimer_hres_active()) {
@@ -901,7 +904,6 @@ static void __remove_hrtimer(struct hrtimer *timer,
                }
 #endif
        }
-       timerqueue_del(&base->active, &timer->node);
        if (!timerqueue_getnext(&base->active))
                base->cpu_base->active_bases &= ~(1 << base->index);
 out:
index 67ce837ae52cdd70115a8ce436f923e96a26adc4..0e2b179bc7b371ea8aa60f52899ae60ff1cb5ec2 100644 (file)
@@ -1596,7 +1596,7 @@ int request_percpu_irq(unsigned int irq, irq_handler_t handler,
                return -ENOMEM;
 
        action->handler = handler;
-       action->flags = IRQF_PERCPU;
+       action->flags = IRQF_PERCPU | IRQF_NO_SUSPEND;
        action->name = devname;
        action->percpu_dev_id = dev_id;
 
index aa57d5da18c1de65e807098702ad9b841fa3788d..dc813a948be2379fe20a0218e1d270212b8408d3 100644 (file)
@@ -84,7 +84,9 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force)
         */
        action = desc->action;
        if (!action || !(action->flags & IRQF_SHARED) ||
-           (action->flags & __IRQF_TIMER) || !action->next)
+           (action->flags & __IRQF_TIMER) ||
+           (action->handler(irq, action->dev_id) == IRQ_HANDLED) ||
+           !action->next)
                goto out;
 
        /* Already running on another processor */
@@ -115,7 +117,7 @@ static int misrouted_irq(int irq)
        struct irq_desc *desc;
        int i, ok = 0;
 
-       if (atomic_inc_return(&irq_poll_active) == 1)
+       if (atomic_inc_return(&irq_poll_active) != 1)
                goto out;
 
        irq_poll_cpu = smp_processor_id();
index b4511b6d3ef93ef5e2d12a097c3a63fa058de423..a6b0503574ee714b2cbe6c871741d298ad9ce5f7 100644 (file)
@@ -55,6 +55,8 @@ enum {
 
 static int hibernation_mode = HIBERNATION_SHUTDOWN;
 
+static bool freezer_test_done;
+
 static const struct platform_hibernation_ops *hibernation_ops;
 
 /**
@@ -345,11 +347,24 @@ int hibernation_snapshot(int platform_mode)
 
        error = freeze_kernel_threads();
        if (error)
-               goto Close;
+               goto Cleanup;
+
+       if (hibernation_test(TEST_FREEZER) ||
+               hibernation_testmode(HIBERNATION_TESTPROC)) {
+
+               /*
+                * Indicate to the caller that we are returning due to a
+                * successful freezer test.
+                */
+               freezer_test_done = true;
+               goto Cleanup;
+       }
 
        error = dpm_prepare(PMSG_FREEZE);
-       if (error)
-               goto Complete_devices;
+       if (error) {
+               dpm_complete(msg);
+               goto Cleanup;
+       }
 
        suspend_console();
        pm_restrict_gfp_mask();
@@ -378,8 +393,6 @@ int hibernation_snapshot(int platform_mode)
                pm_restore_gfp_mask();
 
        resume_console();
-
- Complete_devices:
        dpm_complete(msg);
 
  Close:
@@ -389,6 +402,10 @@ int hibernation_snapshot(int platform_mode)
  Recover_platform:
        platform_recover(platform_mode);
        goto Resume_devices;
+
+ Cleanup:
+       swsusp_free();
+       goto Close;
 }
 
 /**
@@ -641,15 +658,13 @@ int hibernate(void)
        if (error)
                goto Finish;
 
-       if (hibernation_test(TEST_FREEZER))
-               goto Thaw;
-
-       if (hibernation_testmode(HIBERNATION_TESTPROC))
-               goto Thaw;
-
        error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
        if (error)
                goto Thaw;
+       if (freezer_test_done) {
+               freezer_test_done = false;
+               goto Thaw;
+       }
 
        if (in_suspend) {
                unsigned int flags = 0;
index 71f49fe4377e907c85c6d5712335aa56b579a79a..36e0f0903c3245e60d2994121d1aaa28c8fc0a23 100644 (file)
@@ -290,13 +290,14 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
                if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
                        break;
        }
-       if (state < PM_SUSPEND_MAX && *s)
+       if (state < PM_SUSPEND_MAX && *s) {
                error = enter_state(state);
                if (error) {
                        suspend_stats.fail++;
                        dpm_save_failed_errno(error);
                } else
                        suspend_stats.success++;
+       }
 #endif
 
  Exit:
index 56db7514718689444b75996a90aea1aeea497961..995e3bd3417b930902317f9cb0e23dfa4811c36c 100644 (file)
@@ -70,6 +70,7 @@ static struct pm_qos_constraints cpu_dma_constraints = {
 };
 static struct pm_qos_object cpu_dma_pm_qos = {
        .constraints = &cpu_dma_constraints,
+       .name = "cpu_dma_latency",
 };
 
 static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
index cf52fda2e0966d005e152ff8747d5d44db5fbd7a..cfc65e1eb9fbba411fad95fabee1b78f0e6517f3 100644 (file)
@@ -491,6 +491,22 @@ void clocksource_touch_watchdog(void)
        clocksource_resume_watchdog();
 }
 
+/**
+ * clocksource_max_adjustment- Returns max adjustment amount
+ * @cs:         Pointer to clocksource
+ *
+ */
+static u32 clocksource_max_adjustment(struct clocksource *cs)
+{
+       u64 ret;
+       /*
+        * We won't try to correct for more then 11% adjustments (110,000 ppm),
+        */
+       ret = (u64)cs->mult * 11;
+       do_div(ret,100);
+       return (u32)ret;
+}
+
 /**
  * clocksource_max_deferment - Returns max time the clocksource can be deferred
  * @cs:         Pointer to clocksource
@@ -503,25 +519,28 @@ static u64 clocksource_max_deferment(struct clocksource *cs)
        /*
         * Calculate the maximum number of cycles that we can pass to the
         * cyc2ns function without overflowing a 64-bit signed result. The
-        * maximum number of cycles is equal to ULLONG_MAX/cs->mult which
-        * is equivalent to the below.
-        * max_cycles < (2^63)/cs->mult
-        * max_cycles < 2^(log2((2^63)/cs->mult))
-        * max_cycles < 2^(log2(2^63) - log2(cs->mult))
-        * max_cycles < 2^(63 - log2(cs->mult))
-        * max_cycles < 1 << (63 - log2(cs->mult))
+        * maximum number of cycles is equal to ULLONG_MAX/(cs->mult+cs->maxadj)
+        * which is equivalent to the below.
+        * max_cycles < (2^63)/(cs->mult + cs->maxadj)
+        * max_cycles < 2^(log2((2^63)/(cs->mult + cs->maxadj)))
+        * max_cycles < 2^(log2(2^63) - log2(cs->mult + cs->maxadj))
+        * max_cycles < 2^(63 - log2(cs->mult + cs->maxadj))
+        * max_cycles < 1 << (63 - log2(cs->mult + cs->maxadj))
         * Please note that we add 1 to the result of the log2 to account for
         * any rounding errors, ensure the above inequality is satisfied and
         * no overflow will occur.
         */
-       max_cycles = 1ULL << (63 - (ilog2(cs->mult) + 1));
+       max_cycles = 1ULL << (63 - (ilog2(cs->mult + cs->maxadj) + 1));
 
        /*
         * The actual maximum number of cycles we can defer the clocksource is
         * determined by the minimum of max_cycles and cs->mask.
+        * Note: Here we subtract the maxadj to make sure we don't sleep for
+        * too long if there's a large negative adjustment.
         */
        max_cycles = min_t(u64, max_cycles, (u64) cs->mask);
-       max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult, cs->shift);
+       max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult - cs->maxadj,
+                                       cs->shift);
 
        /*
         * To ensure that the clocksource does not wrap whilst we are idle,
@@ -640,7 +659,6 @@ static void clocksource_enqueue(struct clocksource *cs)
 void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq)
 {
        u64 sec;
-
        /*
         * Calc the maximum number of seconds which we can run before
         * wrapping around. For clocksources which have a mask > 32bit
@@ -661,6 +679,20 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq)
 
        clocks_calc_mult_shift(&cs->mult, &cs->shift, freq,
                               NSEC_PER_SEC / scale, sec * scale);
+
+       /*
+        * for clocksources that have large mults, to avoid overflow.
+        * Since mult may be adjusted by ntp, add an safety extra margin
+        *
+        */
+       cs->maxadj = clocksource_max_adjustment(cs);
+       while ((cs->mult + cs->maxadj < cs->mult)
+               || (cs->mult - cs->maxadj > cs->mult)) {
+               cs->mult >>= 1;
+               cs->shift--;
+               cs->maxadj = clocksource_max_adjustment(cs);
+       }
+
        cs->max_idle_ns = clocksource_max_deferment(cs);
 }
 EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale);
@@ -701,6 +733,12 @@ EXPORT_SYMBOL_GPL(__clocksource_register_scale);
  */
 int clocksource_register(struct clocksource *cs)
 {
+       /* calculate max adjustment for given mult/shift */
+       cs->maxadj = clocksource_max_adjustment(cs);
+       WARN_ONCE(cs->mult + cs->maxadj < cs->mult,
+               "Clocksource %s might overflow on 11%% adjustment\n",
+               cs->name);
+
        /* calculate max idle time permitted for this clocksource */
        cs->max_idle_ns = clocksource_max_deferment(cs);
 
index 2b021b0e8507e7e4f9951780c88877bb2d4d56bd..237841378c031ef0f2fa6c492559e695a111b74f 100644 (file)
@@ -249,6 +249,8 @@ ktime_t ktime_get(void)
                secs = xtime.tv_sec + wall_to_monotonic.tv_sec;
                nsecs = xtime.tv_nsec + wall_to_monotonic.tv_nsec;
                nsecs += timekeeping_get_ns();
+               /* If arch requires, add in gettimeoffset() */
+               nsecs += arch_gettimeoffset();
 
        } while (read_seqretry(&xtime_lock, seq));
        /*
@@ -280,6 +282,8 @@ void ktime_get_ts(struct timespec *ts)
                *ts = xtime;
                tomono = wall_to_monotonic;
                nsecs = timekeeping_get_ns();
+               /* If arch requires, add in gettimeoffset() */
+               nsecs += arch_gettimeoffset();
 
        } while (read_seqretry(&xtime_lock, seq));
 
@@ -802,14 +806,44 @@ static void timekeeping_adjust(s64 offset)
        s64 error, interval = timekeeper.cycle_interval;
        int adj;
 
+       /*
+        * The point of this is to check if the error is greater then half
+        * an interval.
+        *
+        * First we shift it down from NTP_SHIFT to clocksource->shifted nsecs.
+        *
+        * Note we subtract one in the shift, so that error is really error*2.
+        * This "saves" dividing(shifting) intererval twice, but keeps the
+        * (error > interval) comparision as still measuring if error is
+        * larger then half an interval.
+        *
+        * Note: It does not "save" on aggrivation when reading the code.
+        */
        error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
        if (error > interval) {
+               /*
+                * We now divide error by 4(via shift), which checks if
+                * the error is greater then twice the interval.
+                * If it is greater, we need a bigadjust, if its smaller,
+                * we can adjust by 1.
+                */
                error >>= 2;
+               /*
+                * XXX - In update_wall_time, we round up to the next
+                * nanosecond, and store the amount rounded up into
+                * the error. This causes the likely below to be unlikely.
+                *
+                * The properfix is to avoid rounding up by using
+                * the high precision timekeeper.xtime_nsec instead of
+                * xtime.tv_nsec everywhere. Fixing this will take some
+                * time.
+                */
                if (likely(error <= interval))
                        adj = 1;
                else
                        adj = timekeeping_bigadjust(error, &interval, &offset);
        } else if (error < -interval) {
+               /* See comment above, this is just switched for the negative */
                error >>= 2;
                if (likely(error >= -interval)) {
                        adj = -1;
@@ -817,9 +851,65 @@ static void timekeeping_adjust(s64 offset)
                        offset = -offset;
                } else
                        adj = timekeeping_bigadjust(error, &interval, &offset);
-       } else
+       } else /* No adjustment needed */
                return;
 
+       WARN_ONCE(timekeeper.clock->maxadj &&
+                       (timekeeper.mult + adj > timekeeper.clock->mult +
+                                               timekeeper.clock->maxadj),
+                       "Adjusting %s more then 11%% (%ld vs %ld)\n",
+                       timekeeper.clock->name, (long)timekeeper.mult + adj,
+                       (long)timekeeper.clock->mult +
+                               timekeeper.clock->maxadj);
+       /*
+        * So the following can be confusing.
+        *
+        * To keep things simple, lets assume adj == 1 for now.
+        *
+        * When adj != 1, remember that the interval and offset values
+        * have been appropriately scaled so the math is the same.
+        *
+        * The basic idea here is that we're increasing the multiplier
+        * by one, this causes the xtime_interval to be incremented by
+        * one cycle_interval. This is because:
+        *      xtime_interval = cycle_interval * mult
+        * So if mult is being incremented by one:
+        *      xtime_interval = cycle_interval * (mult + 1)
+        * Its the same as:
+        *      xtime_interval = (cycle_interval * mult) + cycle_interval
+        * Which can be shortened to:
+        *      xtime_interval += cycle_interval
+        *
+        * So offset stores the non-accumulated cycles. Thus the current
+        * time (in shifted nanoseconds) is:
+        *      now = (offset * adj) + xtime_nsec
+        * Now, even though we're adjusting the clock frequency, we have
+        * to keep time consistent. In other words, we can't jump back
+        * in time, and we also want to avoid jumping forward in time.
+        *
+        * So given the same offset value, we need the time to be the same
+        * both before and after the freq adjustment.
+        *      now = (offset * adj_1) + xtime_nsec_1
+        *      now = (offset * adj_2) + xtime_nsec_2
+        * So:
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * adj_2) + xtime_nsec_2
+        * And we know:
+        *      adj_2 = adj_1 + 1
+        * So:
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * (adj_1+1)) + xtime_nsec_2
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * adj_1) + offset + xtime_nsec_2
+        * Canceling the sides:
+        *      xtime_nsec_1 = offset + xtime_nsec_2
+        * Which gives us:
+        *      xtime_nsec_2 = xtime_nsec_1 - offset
+        * Which simplfies to:
+        *      xtime_nsec -= offset
+        *
+        * XXX - TODO: Doc ntp_error calculation.
+        */
        timekeeper.mult += adj;
        timekeeper.xtime_interval += interval;
        timekeeper.xtime_nsec -= offset;
index ac09f2226dc748132cd869bdf0933a5daf7509c4..a8408b6cacdf7ff8e73fcd3bf7db8a850afb56a4 100644 (file)
@@ -20,6 +20,7 @@ static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = {
        [NLA_U16]       = sizeof(u16),
        [NLA_U32]       = sizeof(u32),
        [NLA_U64]       = sizeof(u64),
+       [NLA_MSECS]     = sizeof(u64),
        [NLA_NESTED]    = NLA_HDRLEN,
 };
 
index a0860640378d87b40827bdb4a89ec271c5c8f35c..71034f41a2ba92ca17c902e2f9b75d568294987f 100644 (file)
@@ -724,6 +724,14 @@ void bdi_destroy(struct backing_dev_info *bdi)
 
        bdi_unregister(bdi);
 
+       /*
+        * If bdi_unregister() had already been called earlier, the
+        * wakeup_timer could still be armed because bdi_prune_sb()
+        * can race with the bdi_wakeup_thread_delayed() calls from
+        * __mark_inode_dirty().
+        */
+       del_timer_sync(&bdi->wb.wakeup_timer);
+
        for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
                percpu_counter_destroy(&bdi->bdi_stat[i]);
 
index dae27ba3be2c8523cd032ad330e2f5a32fbffaf3..bb28a5f9db8ddbf2f65391fe9206ca99b46a256b 100644 (file)
@@ -2422,6 +2422,8 @@ retry_avoidcopy:
         * anon_vma prepared.
         */
        if (unlikely(anon_vma_prepare(vma))) {
+               page_cache_release(new_page);
+               page_cache_release(old_page);
                /* Caller expects lock to be held */
                spin_lock(&mm->page_table_lock);
                return VM_FAULT_OOM;
index 73419c55eda6ddbbdfb3ece3e6d6e477ebd78600..b982290fd962dc2745c423d44e7b92f9c1db247a 100644 (file)
@@ -454,7 +454,7 @@ void  __attribute__((weak)) vmalloc_sync_all(void)
  *     between processes, it syncs the pagetable across all
  *     processes.
  */
-struct vm_struct *alloc_vm_area(size_t size)
+struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes)
 {
        BUG();
        return NULL;
index 471dedb463ab30f9e57d793c5367cac966098c06..76f2c5ae908e85a858c006d932edcdf9128e0cc2 100644 (file)
@@ -185,6 +185,11 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
        if (!p)
                return 0;
 
+       if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
+               task_unlock(p);
+               return 0;
+       }
+
        /*
         * The memory controller may have a limit of 0 bytes, so avoid a divide
         * by zero, if necessary.
index 0360d1b5a1ddd5bc68eb55a1dd1c24f453218aa4..71252486bc6f1f161b87592ded6e8b7e6c0dc8ee 100644 (file)
@@ -128,7 +128,6 @@ unsigned long global_dirty_limit;
  *
  */
 static struct prop_descriptor vm_completions;
-static struct prop_descriptor vm_dirties;
 
 /*
  * couple the period to the dirty_ratio:
@@ -154,7 +153,6 @@ static void update_completion_period(void)
 {
        int shift = calc_period_shift();
        prop_change_shift(&vm_completions, shift);
-       prop_change_shift(&vm_dirties, shift);
 
        writeback_set_ratelimit();
 }
@@ -235,11 +233,6 @@ void bdi_writeout_inc(struct backing_dev_info *bdi)
 }
 EXPORT_SYMBOL_GPL(bdi_writeout_inc);
 
-void task_dirty_inc(struct task_struct *tsk)
-{
-       prop_inc_single(&vm_dirties, &tsk->dirties);
-}
-
 /*
  * Obtain an accurate fraction of the BDI's portion.
  */
@@ -1097,13 +1090,13 @@ static void balance_dirty_pages(struct address_space *mapping,
                pos_ratio = bdi_position_ratio(bdi, dirty_thresh,
                                               background_thresh, nr_dirty,
                                               bdi_thresh, bdi_dirty);
-               if (unlikely(pos_ratio == 0)) {
+               task_ratelimit = ((u64)dirty_ratelimit * pos_ratio) >>
+                                                       RATELIMIT_CALC_SHIFT;
+               if (unlikely(task_ratelimit == 0)) {
                        pause = max_pause;
                        goto pause;
                }
-               task_ratelimit = (u64)dirty_ratelimit *
-                                       pos_ratio >> RATELIMIT_CALC_SHIFT;
-               pause = (HZ * pages_dirtied) / (task_ratelimit | 1);
+               pause = HZ * pages_dirtied / task_ratelimit;
                if (unlikely(pause <= 0)) {
                        trace_balance_dirty_pages(bdi,
                                                  dirty_thresh,
@@ -1133,17 +1126,17 @@ pause:
                                          pages_dirtied,
                                          pause,
                                          start_time);
-               __set_current_state(TASK_UNINTERRUPTIBLE);
+               __set_current_state(TASK_KILLABLE);
                io_schedule_timeout(pause);
 
-               dirty_thresh = hard_dirty_limit(dirty_thresh);
                /*
-                * max-pause area. If dirty exceeded but still within this
-                * area, no need to sleep for more than 200ms: (a) 8 pages per
-                * 200ms is typically more than enough to curb heavy dirtiers;
-                * (b) the pause time limit makes the dirtiers more responsive.
+                * This is typically equal to (nr_dirty < dirty_thresh) and can
+                * also keep "1000+ dd on a slow USB stick" under control.
                 */
-               if (nr_dirty < dirty_thresh)
+               if (task_ratelimit)
+                       break;
+
+               if (fatal_signal_pending(current))
                        break;
        }
 
@@ -1395,7 +1388,6 @@ void __init page_writeback_init(void)
 
        shift = calc_period_shift();
        prop_descriptor_init(&vm_completions, shift);
-       prop_descriptor_init(&vm_dirties, shift);
 }
 
 /**
@@ -1724,7 +1716,6 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)
                __inc_zone_page_state(page, NR_DIRTIED);
                __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE);
                __inc_bdi_stat(mapping->backing_dev_info, BDI_DIRTIED);
-               task_dirty_inc(current);
                task_io_account_write(PAGE_CACHE_SIZE);
        }
 }
index ea534960a04bcda7e87a18cacf67bd2eb1fc5fe0..12a48a88c0d8cb00dd55b2adcea3e536493dee1a 100644 (file)
@@ -50,14 +50,13 @@ static struct page **pcpu_get_pages_and_bitmap(struct pcpu_chunk *chunk,
 
        if (!pages || !bitmap) {
                if (may_alloc && !pages)
-                       pages = pcpu_mem_alloc(pages_size);
+                       pages = pcpu_mem_zalloc(pages_size);
                if (may_alloc && !bitmap)
-                       bitmap = pcpu_mem_alloc(bitmap_size);
+                       bitmap = pcpu_mem_zalloc(bitmap_size);
                if (!pages || !bitmap)
                        return NULL;
        }
 
-       memset(pages, 0, pages_size);
        bitmap_copy(bitmap, chunk->populated, pcpu_unit_pages);
 
        *bitmapp = bitmap;
@@ -143,8 +142,8 @@ static void pcpu_pre_unmap_flush(struct pcpu_chunk *chunk,
                                 int page_start, int page_end)
 {
        flush_cache_vunmap(
-               pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
-               pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+               pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+               pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
 }
 
 static void __pcpu_unmap_pages(unsigned long addr, int nr_pages)
@@ -206,8 +205,8 @@ static void pcpu_post_unmap_tlb_flush(struct pcpu_chunk *chunk,
                                      int page_start, int page_end)
 {
        flush_tlb_kernel_range(
-               pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
-               pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+               pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+               pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
 }
 
 static int __pcpu_map_pages(unsigned long addr, struct page **pages,
@@ -284,8 +283,8 @@ static void pcpu_post_map_flush(struct pcpu_chunk *chunk,
                                int page_start, int page_end)
 {
        flush_cache_vmap(
-               pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
-               pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+               pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+               pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
 }
 
 /**
index bf80e55dbed7e66fcd28f6dbc46c86fbd222a008..3bb810a72006cd65e345e16fd124b61e029964db 100644 (file)
@@ -116,9 +116,9 @@ static int pcpu_atom_size __read_mostly;
 static int pcpu_nr_slots __read_mostly;
 static size_t pcpu_chunk_struct_size __read_mostly;
 
-/* cpus with the lowest and highest unit numbers */
-static unsigned int pcpu_first_unit_cpu __read_mostly;
-static unsigned int pcpu_last_unit_cpu __read_mostly;
+/* cpus with the lowest and highest unit addresses */
+static unsigned int pcpu_low_unit_cpu __read_mostly;
+static unsigned int pcpu_high_unit_cpu __read_mostly;
 
 /* the address of the first chunk which starts with the kernel static area */
 void *pcpu_base_addr __read_mostly;
@@ -273,11 +273,11 @@ static void __maybe_unused pcpu_next_pop(struct pcpu_chunk *chunk,
             (rs) = (re) + 1, pcpu_next_pop((chunk), &(rs), &(re), (end)))
 
 /**
- * pcpu_mem_alloc - allocate memory
+ * pcpu_mem_zalloc - allocate memory
  * @size: bytes to allocate
  *
  * Allocate @size bytes.  If @size is smaller than PAGE_SIZE,
- * kzalloc() is used; otherwise, vmalloc() is used.  The returned
+ * kzalloc() is used; otherwise, vzalloc() is used.  The returned
  * memory is always zeroed.
  *
  * CONTEXT:
@@ -286,7 +286,7 @@ static void __maybe_unused pcpu_next_pop(struct pcpu_chunk *chunk,
  * RETURNS:
  * Pointer to the allocated area on success, NULL on failure.
  */
-static void *pcpu_mem_alloc(size_t size)
+static void *pcpu_mem_zalloc(size_t size)
 {
        if (WARN_ON_ONCE(!slab_is_available()))
                return NULL;
@@ -302,7 +302,7 @@ static void *pcpu_mem_alloc(size_t size)
  * @ptr: memory to free
  * @size: size of the area
  *
- * Free @ptr.  @ptr should have been allocated using pcpu_mem_alloc().
+ * Free @ptr.  @ptr should have been allocated using pcpu_mem_zalloc().
  */
 static void pcpu_mem_free(void *ptr, size_t size)
 {
@@ -384,7 +384,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc)
        size_t old_size = 0, new_size = new_alloc * sizeof(new[0]);
        unsigned long flags;
 
-       new = pcpu_mem_alloc(new_size);
+       new = pcpu_mem_zalloc(new_size);
        if (!new)
                return -ENOMEM;
 
@@ -604,11 +604,12 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void)
 {
        struct pcpu_chunk *chunk;
 
-       chunk = pcpu_mem_alloc(pcpu_chunk_struct_size);
+       chunk = pcpu_mem_zalloc(pcpu_chunk_struct_size);
        if (!chunk)
                return NULL;
 
-       chunk->map = pcpu_mem_alloc(PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0]));
+       chunk->map = pcpu_mem_zalloc(PCPU_DFL_MAP_ALLOC *
+                                               sizeof(chunk->map[0]));
        if (!chunk->map) {
                kfree(chunk);
                return NULL;
@@ -977,6 +978,17 @@ bool is_kernel_percpu_address(unsigned long addr)
  * address.  The caller is responsible for ensuring @addr stays valid
  * until this function finishes.
  *
+ * percpu allocator has special setup for the first chunk, which currently
+ * supports either embedding in linear address space or vmalloc mapping,
+ * and, from the second one, the backing allocator (currently either vm or
+ * km) provides translation.
+ *
+ * The addr can be tranlated simply without checking if it falls into the
+ * first chunk. But the current code reflects better how percpu allocator
+ * actually works, and the verification can discover both bugs in percpu
+ * allocator itself and per_cpu_ptr_to_phys() callers. So we keep current
+ * code.
+ *
  * RETURNS:
  * The physical address for @addr.
  */
@@ -984,19 +996,19 @@ phys_addr_t per_cpu_ptr_to_phys(void *addr)
 {
        void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
        bool in_first_chunk = false;
-       unsigned long first_start, first_end;
+       unsigned long first_low, first_high;
        unsigned int cpu;
 
        /*
-        * The following test on first_start/end isn't strictly
+        * The following test on unit_low/high isn't strictly
         * necessary but will speed up lookups of addresses which
         * aren't in the first chunk.
         */
-       first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0);
-       first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu,
-                                   pcpu_unit_pages);
-       if ((unsigned long)addr >= first_start &&
-           (unsigned long)addr < first_end) {
+       first_low = pcpu_chunk_addr(pcpu_first_chunk, pcpu_low_unit_cpu, 0);
+       first_high = pcpu_chunk_addr(pcpu_first_chunk, pcpu_high_unit_cpu,
+                                    pcpu_unit_pages);
+       if ((unsigned long)addr >= first_low &&
+           (unsigned long)addr < first_high) {
                for_each_possible_cpu(cpu) {
                        void *start = per_cpu_ptr(base, cpu);
 
@@ -1233,7 +1245,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
 
        for (cpu = 0; cpu < nr_cpu_ids; cpu++)
                unit_map[cpu] = UINT_MAX;
-       pcpu_first_unit_cpu = NR_CPUS;
+
+       pcpu_low_unit_cpu = NR_CPUS;
+       pcpu_high_unit_cpu = NR_CPUS;
 
        for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
                const struct pcpu_group_info *gi = &ai->groups[group];
@@ -1253,9 +1267,13 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
                        unit_map[cpu] = unit + i;
                        unit_off[cpu] = gi->base_offset + i * ai->unit_size;
 
-                       if (pcpu_first_unit_cpu == NR_CPUS)
-                               pcpu_first_unit_cpu = cpu;
-                       pcpu_last_unit_cpu = cpu;
+                       /* determine low/high unit_cpu */
+                       if (pcpu_low_unit_cpu == NR_CPUS ||
+                           unit_off[cpu] < unit_off[pcpu_low_unit_cpu])
+                               pcpu_low_unit_cpu = cpu;
+                       if (pcpu_high_unit_cpu == NR_CPUS ||
+                           unit_off[cpu] > unit_off[pcpu_high_unit_cpu])
+                               pcpu_high_unit_cpu = cpu;
                }
        }
        pcpu_nr_units = unit;
@@ -1889,7 +1907,7 @@ void __init percpu_init_late(void)
 
                BUILD_BUG_ON(size > PAGE_SIZE);
 
-               map = pcpu_mem_alloc(size);
+               map = pcpu_mem_zalloc(size);
                BUG_ON(!map);
 
                spin_lock_irqsave(&pcpu_lock, flags);
index 7d2a996c307e4306bd233f4ae340a02d6915ffb1..ed3334d9b6da77f64796f1933f7672284b159fc2 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1862,7 +1862,7 @@ static void unfreeze_partials(struct kmem_cache *s)
 {
        struct kmem_cache_node *n = NULL;
        struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab);
-       struct page *page;
+       struct page *page, *discard_page = NULL;
 
        while ((page = c->partial)) {
                enum slab_modes { M_PARTIAL, M_FREE };
@@ -1904,7 +1904,8 @@ static void unfreeze_partials(struct kmem_cache *s)
                                if (l == M_PARTIAL)
                                        remove_partial(n, page);
                                else
-                                       add_partial(n, page, 1);
+                                       add_partial(n, page,
+                                               DEACTIVATE_TO_TAIL);
 
                                l = m;
                        }
@@ -1915,14 +1916,22 @@ static void unfreeze_partials(struct kmem_cache *s)
                                "unfreezing slab"));
 
                if (m == M_FREE) {
-                       stat(s, DEACTIVATE_EMPTY);
-                       discard_slab(s, page);
-                       stat(s, FREE_SLAB);
+                       page->next = discard_page;
+                       discard_page = page;
                }
        }
 
        if (n)
                spin_unlock(&n->list_lock);
+
+       while (discard_page) {
+               page = discard_page;
+               discard_page = discard_page->next;
+
+               stat(s, DEACTIVATE_EMPTY);
+               discard_slab(s, page);
+               stat(s, FREE_SLAB);
+       }
 }
 
 /*
@@ -1969,7 +1978,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
                page->pobjects = pobjects;
                page->next = oldpage;
 
-       } while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
+       } while (irqsafe_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
        stat(s, CPU_PARTIAL_FREE);
        return pobjects;
 }
@@ -4435,30 +4444,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
 
                for_each_possible_cpu(cpu) {
                        struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu);
+                       int node = ACCESS_ONCE(c->node);
                        struct page *page;
 
-                       if (!c || c->node < 0)
+                       if (node < 0)
                                continue;
-
-                       if (c->page) {
-                                       if (flags & SO_TOTAL)
-                                               x = c->page->objects;
+                       page = ACCESS_ONCE(c->page);
+                       if (page) {
+                               if (flags & SO_TOTAL)
+                                       x = page->objects;
                                else if (flags & SO_OBJECTS)
-                                       x = c->page->inuse;
+                                       x = page->inuse;
                                else
                                        x = 1;
 
                                total += x;
-                               nodes[c->node] += x;
+                               nodes[node] += x;
                        }
                        page = c->partial;
 
                        if (page) {
                                x = page->pobjects;
-                                total += x;
-                                nodes[c->node] += x;
+                               total += x;
+                               nodes[node] += x;
                        }
-                       per_cpu[c->node]++;
+                       per_cpu[node]++;
                }
        }
 
index b669aa6f6caff34f41fac15a527a791576f9026a..3231bf3328781b023c9e3b0b772aa1685c940d31 100644 (file)
@@ -2141,23 +2141,30 @@ void  __attribute__((weak)) vmalloc_sync_all(void)
 
 static int f(pte_t *pte, pgtable_t table, unsigned long addr, void *data)
 {
-       /* apply_to_page_range() does all the hard work. */
+       pte_t ***p = data;
+
+       if (p) {
+               *(*p) = pte;
+               (*p)++;
+       }
        return 0;
 }
 
 /**
  *     alloc_vm_area - allocate a range of kernel address space
  *     @size:          size of the area
+ *     @ptes:          returns the PTEs for the address space
  *
  *     Returns:        NULL on failure, vm_struct on success
  *
  *     This function reserves a range of kernel address space, and
  *     allocates pagetables to map that range.  No actual mappings
- *     are created.  If the kernel address space is not shared
- *     between processes, it syncs the pagetable across all
- *     processes.
+ *     are created.
+ *
+ *     If @ptes is non-NULL, pointers to the PTEs (in init_mm)
+ *     allocated for the VM area are returned.
  */
-struct vm_struct *alloc_vm_area(size_t size)
+struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes)
 {
        struct vm_struct *area;
 
@@ -2171,19 +2178,11 @@ struct vm_struct *alloc_vm_area(size_t size)
         * of kernel virtual address space and mapped into init_mm.
         */
        if (apply_to_page_range(&init_mm, (unsigned long)area->addr,
-                               area->size, f, NULL)) {
+                               size, f, ptes ? &ptes : NULL)) {
                free_vm_area(area);
                return NULL;
        }
 
-       /*
-        * If the allocated address space is passed to a hypercall
-        * before being used then we cannot rely on a page fault to
-        * trigger an update of the page tables.  So sync all the page
-        * tables here.
-        */
-       vmalloc_sync_all();
-
        return area;
 }
 EXPORT_SYMBOL_GPL(alloc_vm_area);
index c1c597e3e198e9ffba26dd4dcf2e59e2ffc923c3..e0af7237cd9245fedfc8886ec446f670ddc48500 100644 (file)
@@ -673,7 +673,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
                goto encrypt;
 
 auth:
-       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+       if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
                return 0;
 
        if (!hci_conn_auth(conn, sec_level, auth_type))
index b84458dcc2261259d83e1bad2aecef95ed622113..be84ae33ae36bec88f4f67502780b4fe5333e270 100644 (file)
@@ -613,7 +613,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
        if (!test_bit(HCI_RAW, &hdev->flags)) {
                set_bit(HCI_INIT, &hdev->flags);
                __hci_request(hdev, hci_reset_req, 0,
-                                       msecs_to_jiffies(250));
+                                       msecs_to_jiffies(HCI_INIT_TIMEOUT));
                clear_bit(HCI_INIT, &hdev->flags);
        }
 
index 8cd12917733b2cb37f21670edd846c9071e19459..5ea94a1eecf2f9a4338aa116d645b03b77fa7bd6 100644 (file)
@@ -251,7 +251,7 @@ static void l2cap_chan_timeout(unsigned long arg)
 
        if (sock_owned_by_user(sk)) {
                /* sk is owned by user. Try again later */
-               __set_chan_timer(chan, HZ / 5);
+               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                bh_unlock_sock(sk);
                chan_put(chan);
                return;
@@ -2488,7 +2488,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
                if (sock_owned_by_user(sk)) {
                        l2cap_state_change(chan, BT_DISCONN);
                        __clear_chan_timer(chan);
-                       __set_chan_timer(chan, HZ / 5);
+                       __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                        break;
                }
 
@@ -2661,7 +2661,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
        default:
                sk->sk_err = ECONNRESET;
-               __set_chan_timer(chan, HZ * 5);
+               __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
                l2cap_send_disconn_req(conn, chan, ECONNRESET);
                goto done;
        }
@@ -2718,7 +2718,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
        if (sock_owned_by_user(sk)) {
                l2cap_state_change(chan, BT_DISCONN);
                __clear_chan_timer(chan);
-               __set_chan_timer(chan, HZ / 5);
+               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                bh_unlock_sock(sk);
                return 0;
        }
@@ -2752,7 +2752,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
        if (sock_owned_by_user(sk)) {
                l2cap_state_change(chan,BT_DISCONN);
                __clear_chan_timer(chan);
-               __set_chan_timer(chan, HZ / 5);
+               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                bh_unlock_sock(sk);
                return 0;
        }
@@ -3998,7 +3998,7 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
        if (encrypt == 0x00) {
                if (chan->sec_level == BT_SECURITY_MEDIUM) {
                        __clear_chan_timer(chan);
-                       __set_chan_timer(chan, HZ * 5);
+                       __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
                } else if (chan->sec_level == BT_SECURITY_HIGH)
                        l2cap_chan_close(chan, ECONNREFUSED);
        } else {
@@ -4066,7 +4066,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                                        L2CAP_CONN_REQ, sizeof(req), &req);
                        } else {
                                __clear_chan_timer(chan);
-                               __set_chan_timer(chan, HZ / 10);
+                               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                        }
                } else if (chan->state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
@@ -4086,7 +4086,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                                }
                        } else {
                                l2cap_state_change(chan, BT_DISCONN);
-                               __set_chan_timer(chan, HZ / 10);
+                               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                                res = L2CAP_CR_SEC_BLOCK;
                                stat = L2CAP_CS_NO_INFO;
                        }
index 940858a48cbdbdbf562ef12645ebdfc568f23d78..2c76342968660f97a1911783f26d60a7a96b715a 100644 (file)
@@ -148,8 +148,6 @@ static int read_index_list(struct sock *sk)
 
                hci_del_off_timer(d);
 
-               set_bit(HCI_MGMT, &d->flags);
-
                if (test_bit(HCI_SETUP, &d->flags))
                        continue;
 
index 38b618c96de64a13a1d724a954352cec27264fae..4e32e18211f9187d8a98a27772a9ba97f5cf7112 100644 (file)
@@ -1802,6 +1802,11 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
                        continue;
                }
 
+               if (test_bit(RFCOMM_ENC_DROP, &d->flags)) {
+                       __rfcomm_dlc_close(d, ECONNREFUSED);
+                       continue;
+               }
+
                if (test_and_clear_bit(RFCOMM_AUTH_ACCEPT, &d->flags)) {
                        rfcomm_dlc_clear_timer(d);
                        if (d->out) {
@@ -2077,7 +2082,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
                if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) {
                        rfcomm_dlc_clear_timer(d);
                        if (status || encrypt == 0x00) {
-                               __rfcomm_dlc_close(d, ECONNREFUSED);
+                               set_bit(RFCOMM_ENC_DROP, &d->flags);
                                continue;
                        }
                }
@@ -2088,7 +2093,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
                                rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
                                continue;
                        } else if (d->sec_level == BT_SECURITY_HIGH) {
-                               __rfcomm_dlc_close(d, ECONNREFUSED);
+                               set_bit(RFCOMM_ENC_DROP, &d->flags);
                                continue;
                        }
                }
index 995cbe0ac0b2b1e74f2b4762d61a13102d9f66bb..a5f4e5769809c74f96c1a93ab67ade401fb022d7 100644 (file)
@@ -1501,6 +1501,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
 
        __skb_pull(skb2, offset);
        skb_reset_transport_header(skb2);
+       skb_postpull_rcsum(skb2, skb_network_header(skb2),
+                          skb_network_header_len(skb2));
 
        icmp6_type = icmp6_hdr(skb2)->icmp6_type;
 
@@ -1770,7 +1772,7 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val)
        int err = 0;
        struct net_bridge_mdb_htable *mdb;
 
-       spin_lock(&br->multicast_lock);
+       spin_lock_bh(&br->multicast_lock);
        if (br->multicast_disabled == !val)
                goto unlock;
 
@@ -1806,7 +1808,7 @@ rollback:
        }
 
 unlock:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock_bh(&br->multicast_lock);
 
        return err;
 }
index 733e46008b89d6e67397d779edf9ccb5cb3e5c8a..f4f3f58f5234c1a5ce5eb4b54638c730f571ffb9 100644 (file)
@@ -244,7 +244,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
                ceph_pagelist_init(req->r_trail);
        }
        /* create request message; allow space for oid */
-       msg_size += 40;
+       msg_size += MAX_OBJ_NAME_SIZE;
        if (snapc)
                msg_size += sizeof(u64) * snapc->num_snaps;
        if (use_mempool)
index c1f4154552fc582320e276e6768831ed9ec32548..36d14406261e8c9ad486103127ae1106baca4678 100644 (file)
@@ -136,8 +136,6 @@ static void ah_output_done(struct crypto_async_request *base, int err)
                memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
        }
 
-       err = ah->nexthdr;
-
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_output_resume(skb, err);
 }
@@ -264,12 +262,12 @@ static void ah_input_done(struct crypto_async_request *base, int err)
        if (err)
                goto out;
 
+       err = ah->nexthdr;
+
        skb->network_header += ah_hlen;
        memcpy(skb_network_header(skb), work_iph, ihl);
        __skb_pull(skb, ah_hlen + ihl);
        skb_set_transport_header(skb, -ihl);
-
-       err = ah->nexthdr;
 out:
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_input_resume(skb, err);
@@ -371,8 +369,6 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
                if (err == -EINPROGRESS)
                        goto out;
 
-               if (err == -EBUSY)
-                       err = NET_XMIT_DROP;
                goto out_free;
        }
 
index f5e2bdaef9495eb52524089f6d9b341cd5503137..68e8ac5143834b80e09cc4bbbbdaecf05a3a2710 100644 (file)
@@ -133,8 +133,8 @@ static int inet_csk_diag_fill(struct sock *sk,
                               &np->rcv_saddr);
                ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
                               &np->daddr);
-               if (ext & (1 << (INET_DIAG_TOS - 1)))
-                       RTA_PUT_U8(skb, INET_DIAG_TOS, np->tclass);
+               if (ext & (1 << (INET_DIAG_TCLASS - 1)))
+                       RTA_PUT_U8(skb, INET_DIAG_TCLASS, np->tclass);
        }
 #endif
 
index ec93335901ddc45d09f7c85c53270ea9a6772207..05d20cca9d66efd2500268a3d0ba4a31117739e7 100644 (file)
@@ -640,6 +640,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
        }
        if (srrptr <= srrspace) {
                opt->srr_is_hit = 1;
+               iph->daddr = nexthop;
                opt->is_changed = 1;
        }
        return 0;
index a06f73fdb3c014e793e50a9ba06363862b3c5eab..43d4c3b223699aee36de3c3c79c6d82b5236a4c0 100644 (file)
@@ -339,7 +339,6 @@ void ping_err(struct sk_buff *skb, u32 info)
        sk = ping_v4_lookup(net, iph->daddr, iph->saddr,
                            ntohs(icmph->un.echo.id), skb->dev->ifindex);
        if (sk == NULL) {
-               ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
                pr_debug("no socket, dropping\n");
                return; /* No socket for error */
        }
@@ -679,7 +678,6 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n",
                inet_sk(sk), inet_sk(sk)->inet_num, skb);
        if (sock_queue_rcv_skb(sk, skb) < 0) {
-               ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_INERRORS);
                kfree_skb(skb);
                pr_debug("ping_queue_rcv_skb -> failed\n");
                return -1;
index 155138d8ec8bb9d7ef0e907b36b0725e0910394d..0c74da8a04732ce9702e9c1c8d80496f1c8df423 100644 (file)
@@ -1304,16 +1304,42 @@ static void rt_del(unsigned hash, struct rtable *rt)
        spin_unlock_bh(rt_hash_lock_addr(hash));
 }
 
+static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
+{
+       struct rtable *rt = (struct rtable *) dst;
+       __be32 orig_gw = rt->rt_gateway;
+       struct neighbour *n, *old_n;
+
+       dst_confirm(&rt->dst);
+
+       rt->rt_gateway = peer->redirect_learned.a4;
+
+       n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
+       if (IS_ERR(n))
+               return PTR_ERR(n);
+       old_n = xchg(&rt->dst._neighbour, n);
+       if (old_n)
+               neigh_release(old_n);
+       if (!n || !(n->nud_state & NUD_VALID)) {
+               if (n)
+                       neigh_event_send(n, NULL);
+               rt->rt_gateway = orig_gw;
+               return -EAGAIN;
+       } else {
+               rt->rt_flags |= RTCF_REDIRECTED;
+               call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+       }
+       return 0;
+}
+
 /* called in rcu_read_lock() section */
 void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                    __be32 saddr, struct net_device *dev)
 {
        int s, i;
        struct in_device *in_dev = __in_dev_get_rcu(dev);
-       struct rtable *rt;
        __be32 skeys[2] = { saddr, 0 };
        int    ikeys[2] = { dev->ifindex, 0 };
-       struct flowi4 fl4;
        struct inet_peer *peer;
        struct net *net;
 
@@ -1336,33 +1362,42 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                        goto reject_redirect;
        }
 
-       memset(&fl4, 0, sizeof(fl4));
-       fl4.daddr = daddr;
        for (s = 0; s < 2; s++) {
                for (i = 0; i < 2; i++) {
-                       fl4.flowi4_oif = ikeys[i];
-                       fl4.saddr = skeys[s];
-                       rt = __ip_route_output_key(net, &fl4);
-                       if (IS_ERR(rt))
-                               continue;
-
-                       if (rt->dst.error || rt->dst.dev != dev ||
-                           rt->rt_gateway != old_gw) {
-                               ip_rt_put(rt);
-                               continue;
-                       }
+                       unsigned int hash;
+                       struct rtable __rcu **rthp;
+                       struct rtable *rt;
+
+                       hash = rt_hash(daddr, skeys[s], ikeys[i], rt_genid(net));
+
+                       rthp = &rt_hash_table[hash].chain;
+
+                       while ((rt = rcu_dereference(*rthp)) != NULL) {
+                               rthp = &rt->dst.rt_next;
+
+                               if (rt->rt_key_dst != daddr ||
+                                   rt->rt_key_src != skeys[s] ||
+                                   rt->rt_oif != ikeys[i] ||
+                                   rt_is_input_route(rt) ||
+                                   rt_is_expired(rt) ||
+                                   !net_eq(dev_net(rt->dst.dev), net) ||
+                                   rt->dst.error ||
+                                   rt->dst.dev != dev ||
+                                   rt->rt_gateway != old_gw)
+                                       continue;
 
-                       if (!rt->peer)
-                               rt_bind_peer(rt, rt->rt_dst, 1);
+                               if (!rt->peer)
+                                       rt_bind_peer(rt, rt->rt_dst, 1);
 
-                       peer = rt->peer;
-                       if (peer) {
-                               peer->redirect_learned.a4 = new_gw;
-                               atomic_inc(&__rt_peer_genid);
+                               peer = rt->peer;
+                               if (peer) {
+                                       if (peer->redirect_learned.a4 != new_gw) {
+                                               peer->redirect_learned.a4 = new_gw;
+                                               atomic_inc(&__rt_peer_genid);
+                                       }
+                                       check_peer_redir(&rt->dst, peer);
+                               }
                        }
-
-                       ip_rt_put(rt);
-                       return;
                }
        }
        return;
@@ -1649,33 +1684,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
        }
 }
 
-static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
-{
-       struct rtable *rt = (struct rtable *) dst;
-       __be32 orig_gw = rt->rt_gateway;
-       struct neighbour *n, *old_n;
-
-       dst_confirm(&rt->dst);
-
-       rt->rt_gateway = peer->redirect_learned.a4;
-
-       n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
-       if (IS_ERR(n))
-               return PTR_ERR(n);
-       old_n = xchg(&rt->dst._neighbour, n);
-       if (old_n)
-               neigh_release(old_n);
-       if (!n || !(n->nud_state & NUD_VALID)) {
-               if (n)
-                       neigh_event_send(n, NULL);
-               rt->rt_gateway = orig_gw;
-               return -EAGAIN;
-       } else {
-               rt->rt_flags |= RTCF_REDIRECTED;
-               call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
-       }
-       return 0;
-}
 
 static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 {
@@ -2845,7 +2853,7 @@ static int rt_fill_info(struct net *net,
        struct rtable *rt = skb_rtable(skb);
        struct rtmsg *r;
        struct nlmsghdr *nlh;
-       long expires = 0;
+       unsigned long expires = 0;
        const struct inet_peer *peer = rt->peer;
        u32 id = 0, ts = 0, tsage = 0, error;
 
@@ -2902,8 +2910,12 @@ static int rt_fill_info(struct net *net,
                        tsage = get_seconds() - peer->tcp_ts_stamp;
                }
                expires = ACCESS_ONCE(peer->pmtu_expires);
-               if (expires)
-                       expires -= jiffies;
+               if (expires) {
+                       if (time_before(jiffies, expires))
+                               expires -= jiffies;
+                       else
+                               expires = 0;
+               }
        }
 
        if (rt_is_input_route(rt)) {
index a7443159c400450e73ff9b83230fe40a48d0da39..a9db4b1a22156dc944addbf661187b2e71070875 100644 (file)
@@ -1510,6 +1510,7 @@ exit:
        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
        return NULL;
 put_and_exit:
+       tcp_clear_xmit_timers(newsk);
        bh_unlock_sock(newsk);
        sock_put(newsk);
        goto exit;
index 980b98f6288c3f82f85da0ac61f74ecfa0cbc12b..63170e29754003c78b2cce548425ae1710c317c4 100644 (file)
@@ -1382,7 +1382,7 @@ static inline int tcp_minshall_check(const struct tcp_sock *tp)
 /* Return 0, if packet can be sent now without violation Nagle's rules:
  * 1. It is full sized.
  * 2. Or it contains FIN. (already checked by caller)
- * 3. Or TCP_NODELAY was set.
+ * 3. Or TCP_CORK is not set, and TCP_NODELAY is set.
  * 4. Or TCP_CORK is not set, and all sent packets are ACKed.
  *    With Minshall's modification: all sent small packets are ACKed.
  */
index 2195ae651923e0e3242c3e61738fed91d19711ff..4c0f894d08432564899bb5611483f5dab3d2ae59 100644 (file)
@@ -324,8 +324,6 @@ static void ah6_output_done(struct crypto_async_request *base, int err)
 #endif
        }
 
-       err = ah->nexthdr;
-
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_output_resume(skb, err);
 }
@@ -466,12 +464,12 @@ static void ah6_input_done(struct crypto_async_request *base, int err)
        if (err)
                goto out;
 
+       err = ah->nexthdr;
+
        skb->network_header += ah_hlen;
        memcpy(skb_network_header(skb), work_iph, hdr_len);
        __skb_pull(skb, ah_hlen + hdr_len);
        skb_set_transport_header(skb, -hdr_len);
-
-       err = ah->nexthdr;
 out:
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_input_resume(skb, err);
@@ -583,8 +581,6 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
                if (err == -EINPROGRESS)
                        goto out;
 
-               if (err == -EBUSY)
-                       err = NET_XMIT_DROP;
                goto out_free;
        }
 
index 027c7ff6f1e5370bc0e84d8e3daeb996875a431c..a46c64eb0a660b47b132e4b2346e1c112cc05759 100644 (file)
@@ -111,6 +111,14 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
            ipv6_addr_loopback(&hdr->daddr))
                goto err;
 
+       /*
+        * RFC4291 2.7
+        * Multicast addresses must not be used as source addresses in IPv6
+        * packets or appear in any Routing header.
+        */
+       if (ipv6_addr_is_multicast(&hdr->saddr))
+               goto err;
+
        skb->transport_header = skb->network_header + sizeof(*hdr);
        IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
 
index bdc15c9003d781fbdb3d0288cf8b88aa84f71742..4e2e9ff67ef29701d4add34b20a63559aa950b4f 100644 (file)
@@ -289,6 +289,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p)
        if ((err = register_netdevice(dev)) < 0)
                goto failed_free;
 
+       strcpy(t->parms.name, dev->name);
+
        dev_hold(dev);
        ip6_tnl_link(ip6n, t);
        return t;
@@ -1407,7 +1409,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
        struct ip6_tnl *t = netdev_priv(dev);
 
        t->dev = dev;
-       strcpy(t->parms.name, dev->name);
        dev->tstats = alloc_percpu(struct pcpu_tstats);
        if (!dev->tstats)
                return -ENOMEM;
@@ -1487,6 +1488,7 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n)
 static int __net_init ip6_tnl_init_net(struct net *net)
 {
        struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+       struct ip6_tnl *t = NULL;
        int err;
 
        ip6n->tnls[0] = ip6n->tnls_wc;
@@ -1507,6 +1509,10 @@ static int __net_init ip6_tnl_init_net(struct net *net)
        err = register_netdev(ip6n->fb_tnl_dev);
        if (err < 0)
                goto err_register;
+
+       t = netdev_priv(ip6n->fb_tnl_dev);
+
+       strcpy(t->parms.name, ip6n->fb_tnl_dev->name);
        return 0;
 
 err_register:
index bf8d50c67931e8e588520b7c49ad49fca51b40b3..cf0f308abf5e7324aa05a40cfffd4eee166b0d51 100644 (file)
@@ -756,9 +756,6 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
                goto error;
        }
 
-       /* Point to L2TP header */
-       optr = ptr = skb->data;
-
        /* Trace packet contents, if enabled */
        if (tunnel->debug & L2TP_MSG_DATA) {
                length = min(32u, skb->len);
@@ -769,12 +766,15 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
 
                offset = 0;
                do {
-                       printk(" %02X", ptr[offset]);
+                       printk(" %02X", skb->data[offset]);
                } while (++offset < length);
 
                printk("\n");
        }
 
+       /* Point to L2TP header */
+       optr = ptr = skb->data;
+
        /* Get L2TP header flags */
        hdrflags = ntohs(*(__be16 *) ptr);
 
index ebd7fb101fbfb26dc7e7850eae1a0c7d14283d9a..d06c65fa5526a88739a647b809067f37fd64fc24 100644 (file)
@@ -832,6 +832,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (is_multicast_ether_addr(mac))
                return -EINVAL;
 
+       /* Only TDLS-supporting stations can add TDLS peers */
+       if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
+           !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
+             sdata->vif.type == NL80211_IFTYPE_STATION))
+               return -ENOTSUPP;
+
        sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
        if (!sta)
                return -ENOMEM;
@@ -841,12 +847,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 
        sta_apply_parameters(local, sta, params);
 
-       /* Only TDLS-supporting stations can add TDLS peers */
-       if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
-           !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
-             sdata->vif.type == NL80211_IFTYPE_STATION))
-               return -ENOTSUPP;
-
        rate_control_rate_init(sta);
 
        layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
index 4c3d1f591bec1c3fc4ee24c447a75a58bf926bf7..ea10a51babda9fa113c84ee000d46c62b86e69c6 100644 (file)
@@ -389,6 +389,7 @@ struct ieee80211_if_managed {
 
        unsigned long timers_running; /* used for quiesce/restart */
        bool powersave; /* powersave requested for this iface */
+       bool broken_ap; /* AP is broken -- turn off powersave */
        enum ieee80211_smps_mode req_smps, /* requested smps mode */
                                 ap_smps, /* smps mode AP thinks we're in */
                                 driver_smps_mode; /* smps mode request */
index 96f9fae32495a8af1c46dfcd7d7ffcb7d16d2d0b..b1b1bb368f701f61b47da0040ce9b0b477d09deb 100644 (file)
@@ -639,6 +639,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
        if (!mgd->powersave)
                return false;
 
+       if (mgd->broken_ap)
+               return false;
+
        if (!mgd->associated)
                return false;
 
@@ -1484,6 +1487,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
        int i, j, err;
        bool have_higher_than_11mbit = false;
        u16 ap_ht_cap_flags;
+       int min_rate = INT_MAX, min_rate_index = -1;
 
        /* AssocResp and ReassocResp have identical structure */
 
@@ -1491,10 +1495,21 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
        capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
 
        if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
-               printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
-                      "set\n", sdata->name, aid);
+               printk(KERN_DEBUG
+                      "%s: invalid AID value 0x%x; bits 15:14 not set\n",
+                      sdata->name, aid);
        aid &= ~(BIT(15) | BIT(14));
 
+       ifmgd->broken_ap = false;
+
+       if (aid == 0 || aid > IEEE80211_MAX_AID) {
+               printk(KERN_DEBUG
+                      "%s: invalid AID value %d (out of range), turn off PS\n",
+                      sdata->name, aid);
+               aid = 0;
+               ifmgd->broken_ap = true;
+       }
+
        pos = mgmt->u.assoc_resp.variable;
        ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
 
@@ -1539,6 +1554,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
                                rates |= BIT(j);
                                if (is_basic)
                                        basic_rates |= BIT(j);
+                               if (rate < min_rate) {
+                                       min_rate = rate;
+                                       min_rate_index = j;
+                               }
                                break;
                        }
                }
@@ -1556,11 +1575,25 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
                                rates |= BIT(j);
                                if (is_basic)
                                        basic_rates |= BIT(j);
+                               if (rate < min_rate) {
+                                       min_rate = rate;
+                                       min_rate_index = j;
+                               }
                                break;
                        }
                }
        }
 
+       /*
+        * some buggy APs don't advertise basic_rates. use the lowest
+        * supported rate instead.
+        */
+       if (unlikely(!basic_rates) && min_rate_index >= 0) {
+               printk(KERN_DEBUG "%s: No basic rates in AssocResp. "
+                      "Using min supported rate instead.\n", sdata->name);
+               basic_rates = BIT(min_rate_index);
+       }
+
        sta->sta.supp_rates[wk->chan->band] = rates;
        sdata->vif.bss_conf.basic_rates = basic_rates;
 
@@ -2255,6 +2288,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
 
        cancel_work_sync(&ifmgd->request_smps_work);
 
+       cancel_work_sync(&ifmgd->monitor_work);
        cancel_work_sync(&ifmgd->beacon_connection_loss_work);
        if (del_timer_sync(&ifmgd->timer))
                set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@@ -2263,7 +2297,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
        if (del_timer_sync(&ifmgd->chswitch_timer))
                set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
 
-       cancel_work_sync(&ifmgd->monitor_work);
        /* these will just be re-established on connection */
        del_timer_sync(&ifmgd->conn_mon_timer);
        del_timer_sync(&ifmgd->bcn_mon_timer);
index bb53726cb04a6d1395f7738e87e58845df3716bf..fb123e2e081a4c51495331f4d8cad945e53c3f40 100644 (file)
@@ -141,8 +141,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        pos++;
 
        /* IEEE80211_RADIOTAP_RATE */
-       if (status->flag & RX_FLAG_HT) {
+       if (!rate || status->flag & RX_FLAG_HT) {
                /*
+                * Without rate information don't add it. If we have,
                 * MCS information is a separate field in radiotap,
                 * added below. The byte here is needed as padding
                 * for the channel though, so initialise it to 0.
@@ -163,12 +164,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        else if (status->flag & RX_FLAG_HT)
                put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
                                   pos);
-       else if (rate->flags & IEEE80211_RATE_ERP_G)
+       else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
                put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
                                   pos);
-       else
+       else if (rate)
                put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
                                   pos);
+       else
+               put_unaligned_le16(IEEE80211_CHAN_2GHZ, pos);
        pos += 2;
 
        /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
index ce962d2c8782e5ec148884ca1ef90a0aaa8e6c18..8eaa746ec7a26d7281e28d42ed3064eb970c874c 100644 (file)
@@ -1354,12 +1354,12 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
                         * Use MoreData flag to indicate whether there are
                         * more buffered frames for this STA
                         */
-                       if (!more_data)
-                               hdr->frame_control &=
-                                       cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
-                       else
+                       if (more_data || !skb_queue_empty(&frames))
                                hdr->frame_control |=
                                        cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+                       else
+                               hdr->frame_control &=
+                                       cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
 
                        if (ieee80211_is_data_qos(hdr->frame_control) ||
                            ieee80211_is_qos_nullfunc(hdr->frame_control))
index 51e256c5fb78801f8fd570192a78c38367ec9bf2..eca0fad09709518266d9aed37c61f75e2f05afcf 100644 (file)
@@ -881,6 +881,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
        skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
                                     ssid, ssid_len,
                                     buf, buf_len);
+       if (!skb)
+               goto out;
 
        if (dst) {
                mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -889,6 +891,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
        }
 
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+
+ out:
        kfree(buf);
 
        return skb;
index 94472eb34d76452acfddfb624eba7e44f46e3445..6c53b6d1002b5a2046837fe2ec60d7687bd0c973 100644 (file)
@@ -1084,14 +1084,13 @@ static void ieee80211_work_work(struct work_struct *work)
                        continue;
                if (wk->chan != local->tmp_channel)
                        continue;
-               if (ieee80211_work_ct_coexists(wk->chan_type,
-                                              local->tmp_channel_type))
+               if (!ieee80211_work_ct_coexists(wk->chan_type,
+                                               local->tmp_channel_type))
                        continue;
                remain_off_channel = true;
        }
 
        if (!remain_off_channel && local->tmp_channel) {
-               bool on_oper_chan = ieee80211_cfg_on_oper_channel(local);
                local->tmp_channel = NULL;
                /* If tmp_channel wasn't operating channel, then
                 * we need to go back on-channel.
@@ -1101,7 +1100,7 @@ static void ieee80211_work_work(struct work_struct *work)
                 * we still need to do a hardware config.  Currently,
                 * we cannot be here while scanning, however.
                 */
-               if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan)
+               if (!ieee80211_cfg_on_oper_channel(local))
                        ieee80211_hw_config(local, 0);
 
                /* At the least, we need to disable offchannel_ps,
index 4cf6dc7910e4b0c13a2baf32447bd9000feb1f19..ec753b3ae72ade6005cecee012ec1e2759a7fb45 100644 (file)
@@ -9,7 +9,6 @@ config RDS
 
 config RDS_RDMA
        tristate "RDS over Infiniband and iWARP"
-       select LLIST
        depends on RDS && INFINIBAND && INFINIBAND_ADDR_TRANS
        ---help---
          Allow RDS to use Infiniband and iWARP as a transport.
index d7f97ef265904f0ddc0d691360f1e920dc63210b..55472c48825e6fd43c3357a2f58b398231a2767e 100644 (file)
@@ -496,7 +496,7 @@ static int xs_nospace(struct rpc_task *task)
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
-       int ret = 0;
+       int ret = -EAGAIN;
 
        dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
                        task->tk_pid, req->rq_slen - req->rq_bytes_sent,
@@ -508,7 +508,6 @@ static int xs_nospace(struct rpc_task *task)
        /* Don't race with disconnect */
        if (xprt_connected(xprt)) {
                if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
-                       ret = -EAGAIN;
                        /*
                         * Notify TCP that we're limited by the application
                         * window size
@@ -2530,8 +2529,10 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
                int err;
                err = xs_init_anyaddr(args->dstaddr->sa_family,
                                        (struct sockaddr *)&new->srcaddr);
-               if (err != 0)
+               if (err != 0) {
+                       xprt_free(xprt);
                        return ERR_PTR(err);
+               }
        }
 
        return xprt;
index f346395314ba8ba6ba9c3754c91bcf18b735b80f..c43612ee96bb517ea2b2f806e5e999e39c6cbc0c 100644 (file)
@@ -81,7 +81,6 @@ static struct proc_dir_entry *proc_router;
  *     Iterator
  */
 static void *r_start(struct seq_file *m, loff_t *pos)
-       __acquires(kernel_lock)
 {
        struct wan_device *wandev;
        loff_t l = *pos;
@@ -103,7 +102,6 @@ static void *r_next(struct seq_file *m, void *v, loff_t *pos)
 }
 
 static void r_stop(struct seq_file *m, void *v)
-       __releases(kernel_lock)
 {
        mutex_unlock(&config_mutex);
 }
index 48260c2d092a820873f10769b9100a7864e8d2e0..b3a476fe82725f738f5215b32cdf2296970451d2 100644 (file)
@@ -132,8 +132,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
        [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
 
-       [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
-                                        .len = NL80211_HT_CAPABILITY_LEN },
+       [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN },
 
        [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
        [NL80211_ATTR_IE] = { .type = NLA_BINARY,
@@ -1253,6 +1252,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                        goto bad_res;
                }
 
+               if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+                   netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
+                       result = -EINVAL;
+                       goto bad_res;
+               }
+
                nla_for_each_nested(nl_txq_params,
                                    info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
                                    rem_txq_params) {
index 6acba9d18cc873cb97b6c190d526985704371876..e71f5a66574e31cb1d4e44429402ddcb5a61a529 100644 (file)
@@ -2265,6 +2265,9 @@ void /* __init_or_exit */ regulatory_exit(void)
 
        kfree(last_request);
 
+       last_request = NULL;
+       dev_set_uevent_suppress(&reg_pdev->dev, true);
+
        platform_device_unregister(reg_pdev);
 
        spin_lock_bh(&reg_pending_beacons_lock);
index 0fb1424104047ced0d99949be89388509e05fc5c..dc23b31594e0f54758d0b59ffa5854c6e426e2e8 100644 (file)
@@ -259,17 +259,20 @@ static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
 {
        const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
        const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
-       int r;
 
+       /* equal if both missing */
        if (!ie1 && !ie2)
                return 0;
-       if (!ie1 || !ie2)
+       /* sort missing IE before (left of) present IE */
+       if (!ie1)
                return -1;
+       if (!ie2)
+               return 1;
 
-       r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1]));
-       if (r == 0 && ie1[1] != ie2[1])
+       /* sort by length first, then by contents */
+       if (ie1[1] != ie2[1])
                return ie2[1] - ie1[1];
-       return r;
+       return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
 }
 
 static bool is_bss(struct cfg80211_bss *a,
index 6bc7a86d1027cbf5f78b67804448f577e869d093..d6f8433250a5a37db4543b61c1b73303f92be574 100644 (file)
@@ -2,5 +2,9 @@
 # Makefile for encrypted keys
 #
 
-obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o
-obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o
+obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys.o
+
+encrypted-keys-y := encrypted.o ecryptfs_format.o
+masterkey-$(CONFIG_TRUSTED_KEYS) := masterkey_trusted.o
+masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_trusted.o
+encrypted-keys-y += $(masterkey-y) $(masterkey-m-m)
index dcc843cb0f80de0f899ada23d8bf80d25e023e5e..41144f71d6154f612570f8f2c5243269becf68a4 100644 (file)
@@ -444,7 +444,7 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
                goto out;
 
        if (IS_ERR(mkey)) {
-               int ret = PTR_ERR(epayload);
+               int ret = PTR_ERR(mkey);
 
                if (ret == -ENOTSUPP)
                        pr_info("encrypted_key: key %s not supported",
index b6ade8945250c0b3f13913c56ee5b9686a3f39d1..8136a2d44c63ddb3a76f30f35b6780ff19b74ae9 100644 (file)
@@ -2,7 +2,8 @@
 #define __ENCRYPTED_KEY_H
 
 #define ENCRYPTED_DEBUG 0
-#ifdef CONFIG_TRUSTED_KEYS
+#if defined(CONFIG_TRUSTED_KEYS) || \
+  (defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE))
 extern struct key *request_trusted_key(const char *trusted_desc,
                                       u8 **master_key, size_t *master_keylen);
 #else
index 5b366d7af3c4dc17b595c67af3dbe99d5fd69df1..69ff52c08e97bb0eab715b1ea61c709e4f80faad 100644 (file)
@@ -102,7 +102,8 @@ int user_update(struct key *key, const void *data, size_t datalen)
                key->expiry = 0;
        }
 
-       kfree_rcu(zap, rcu);
+       if (zap)
+               kfree_rcu(zap, rcu);
 
 error:
        return ret;
index 6aceef518a41fe7cd095bf8f860afe210abeb6ce..5c32f36ff70618dfb08e3040c94060238dfa44da 100644 (file)
@@ -102,9 +102,6 @@ static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
 
 const char *smack_cipso_option = SMACK_CIPSO_OPTION;
 
-
-#define        SEQ_READ_FINISHED       ((loff_t)-1)
-
 /*
  * Values for parsing cipso rules
  * SMK_DIGITLEN: Length of a digit field in a rule.
@@ -357,10 +354,12 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
 
        rc = count;
        /*
+        * If this is "load" as opposed to "load-self" and a new rule
+        * it needs to get added for reporting.
         * smk_set_access returns true if there was already a rule
         * for the subject/object pair, and false if it was new.
         */
-       if (!smk_set_access(rule, rule_list, rule_lock)) {
+       if (load && !smk_set_access(rule, rule_list, rule_lock)) {
                smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
                if (smlp != NULL) {
                        smlp->smk_rule = rule;
@@ -377,12 +376,12 @@ out:
        return rc;
 }
 
-
 /*
- * Seq_file read operations for /smack/load
+ * Core logic for smackfs seq list operations.
  */
 
-static void *load_seq_start(struct seq_file *s, loff_t *pos)
+static void *smk_seq_start(struct seq_file *s, loff_t *pos,
+                               struct list_head *head)
 {
        struct list_head *list;
 
@@ -390,7 +389,7 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
         * This is 0 the first time through.
         */
        if (s->index == 0)
-               s->private = &smack_rule_list;
+               s->private = head;
 
        if (s->private == NULL)
                return NULL;
@@ -404,11 +403,12 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
        return list;
 }
 
-static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
+                               struct list_head *head)
 {
        struct list_head *list = v;
 
-       if (list_is_last(list, &smack_rule_list)) {
+       if (list_is_last(list, head)) {
                s->private = NULL;
                return NULL;
        }
@@ -416,6 +416,25 @@ static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
        return list->next;
 }
 
+static void smk_seq_stop(struct seq_file *s, void *v)
+{
+       /* No-op */
+}
+
+/*
+ * Seq_file read operations for /smack/load
+ */
+
+static void *load_seq_start(struct seq_file *s, loff_t *pos)
+{
+       return smk_seq_start(s, pos, &smack_rule_list);
+}
+
+static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+       return smk_seq_next(s, v, pos, &smack_rule_list);
+}
+
 static int load_seq_show(struct seq_file *s, void *v)
 {
        struct list_head *list = v;
@@ -446,16 +465,11 @@ static int load_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void load_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations load_seq_ops = {
        .start = load_seq_start,
        .next  = load_seq_next,
        .show  = load_seq_show,
-       .stop  = load_seq_stop,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -574,28 +588,12 @@ static void smk_unlbl_ambient(char *oldambient)
 
 static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
 {
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&smack_known_list))
-               return NULL;
-
-       return smack_known_list.next;
+       return smk_seq_start(s, pos, &smack_known_list);
 }
 
 static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct list_head  *list = v;
-
-       /*
-        * labels with no associated cipso value wont be printed
-        * in cipso_seq_show
-        */
-       if (list_is_last(list, &smack_known_list)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-
-       return list->next;
+       return smk_seq_next(s, v, pos, &smack_known_list);
 }
 
 /*
@@ -634,16 +632,11 @@ static int cipso_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void cipso_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations cipso_seq_ops = {
        .start = cipso_seq_start,
-       .stop  = cipso_seq_stop,
        .next  = cipso_seq_next,
        .show  = cipso_seq_show,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -788,23 +781,12 @@ static const struct file_operations smk_cipso_ops = {
 
 static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
 {
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&smk_netlbladdr_list))
-               return NULL;
-       return smk_netlbladdr_list.next;
+       return smk_seq_start(s, pos, &smk_netlbladdr_list);
 }
 
 static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct list_head *list = v;
-
-       if (list_is_last(list, &smk_netlbladdr_list)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-
-       return list->next;
+       return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
 }
 #define BEBITS (sizeof(__be32) * 8)
 
@@ -828,16 +810,11 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void netlbladdr_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations netlbladdr_seq_ops = {
        .start = netlbladdr_seq_start,
-       .stop  = netlbladdr_seq_stop,
        .next  = netlbladdr_seq_next,
        .show  = netlbladdr_seq_show,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -1405,23 +1382,14 @@ static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
 {
        struct task_smack *tsp = current_security();
 
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&tsp->smk_rules))
-               return NULL;
-       return tsp->smk_rules.next;
+       return smk_seq_start(s, pos, &tsp->smk_rules);
 }
 
 static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
        struct task_smack *tsp = current_security();
-       struct list_head *list = v;
 
-       if (list_is_last(list, &tsp->smk_rules)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-       return list->next;
+       return smk_seq_next(s, v, pos, &tsp->smk_rules);
 }
 
 static int load_self_seq_show(struct seq_file *s, void *v)
@@ -1453,16 +1421,11 @@ static int load_self_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void load_self_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations load_self_seq_ops = {
        .start = load_self_seq_start,
        .next  = load_self_seq_next,
        .show  = load_self_seq_show,
-       .stop  = load_self_seq_stop,
+       .stop  = smk_seq_stop,
 };
 
 
index 5dbab38d04af77872b2f8b149e2dbe6c228bc9fa..130cfe677d60a1ef8bf996c0a61bc0dea35a9da6 100644 (file)
@@ -52,6 +52,7 @@ struct link_slave {
        struct link_ctl_info info;
        int vals[2];            /* current values */
        unsigned int flags;
+       struct snd_kcontrol *kctl; /* original kcontrol pointer */
        struct snd_kcontrol slave; /* the copy of original control entry */
 };
 
@@ -252,6 +253,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
                       slave->count * sizeof(*slave->vd), GFP_KERNEL);
        if (!srec)
                return -ENOMEM;
+       srec->kctl = slave;
        srec->slave = *slave;
        memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
        srec->master = master_link;
@@ -333,10 +335,18 @@ static int master_put(struct snd_kcontrol *kcontrol,
 static void master_free(struct snd_kcontrol *kcontrol)
 {
        struct link_master *master = snd_kcontrol_chip(kcontrol);
-       struct link_slave *slave;
-
-       list_for_each_entry(slave, &master->slaves, list)
-               slave->master = NULL;
+       struct link_slave *slave, *n;
+
+       /* free all slave links and retore the original slave kctls */
+       list_for_each_entry_safe(slave, n, &master->slaves, list) {
+               struct snd_kcontrol *sctl = slave->kctl;
+               struct list_head olist = sctl->list;
+               memcpy(sctl, &slave->slave, sizeof(*sctl));
+               memcpy(sctl->vd, slave->slave.vd,
+                      sctl->count * sizeof(*sctl->vd));
+               sctl->list = olist; /* keep the current linked-list */
+               kfree(slave);
+       }
        kfree(master);
 }
 
index e083122ca55af550f6d4b72e6d5cea5c8c2e1a05..dbf94b189e7576b6e8a3194c5612b0397e6060ee 100644 (file)
@@ -148,7 +148,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au,
                struct cs5535audio_dma_desc *desc =
                        &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[i];
                desc->addr = cpu_to_le32(addr);
-               desc->size = cpu_to_le32(period_bytes);
+               desc->size = cpu_to_le16(period_bytes);
                desc->ctlreserved = cpu_to_le16(PRD_EOP);
                desc_addr += sizeof(struct cs5535audio_dma_desc);
                addr += period_bytes;
index 916a1863af73b6a3df0e6c79ae97a4ce0c5db2f7..4562e9de6a1ab0dc7015e28d7be14c2eafa5a6b3 100644 (file)
@@ -2331,6 +2331,39 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        return 0;
 }
 
+typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
+
+/* apply the function to all matching slave ctls in the mixer list */
+static int map_slaves(struct hda_codec *codec, const char * const *slaves,
+                     map_slave_func_t func, void *data) 
+{
+       struct hda_nid_item *items;
+       const char * const *s;
+       int i, err;
+
+       items = codec->mixers.list;
+       for (i = 0; i < codec->mixers.used; i++) {
+               struct snd_kcontrol *sctl = items[i].kctl;
+               if (!sctl || !sctl->id.name ||
+                   sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
+                       continue;
+               for (s = slaves; *s; s++) {
+                       if (!strcmp(sctl->id.name, *s)) {
+                               err = func(data, sctl);
+                               if (err)
+                                       return err;
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int check_slave_present(void *data, struct snd_kcontrol *sctl)
+{
+       return 1;
+}
+
 /**
  * snd_hda_add_vmaster - create a virtual master control and add slaves
  * @codec: HD-audio codec
@@ -2351,12 +2384,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
                        unsigned int *tlv, const char * const *slaves)
 {
        struct snd_kcontrol *kctl;
-       const char * const *s;
        int err;
 
-       for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
-               ;
-       if (!*s) {
+       err = map_slaves(codec, slaves, check_slave_present, NULL);
+       if (err != 1) {
                snd_printdd("No slave found for %s\n", name);
                return 0;
        }
@@ -2367,23 +2398,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
        if (err < 0)
                return err;
 
-       for (s = slaves; *s; s++) {
-               struct snd_kcontrol *sctl;
-               int i = 0;
-               for (;;) {
-                       sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
-                       if (!sctl) {
-                               if (!i)
-                                       snd_printdd("Cannot find slave %s, "
-                                                   "skipped\n", *s);
-                               break;
-                       }
-                       err = snd_ctl_add_slave(kctl, sctl);
-                       if (err < 0)
-                               return err;
-                       i++;
-               }
-       }
+       err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave,
+                        kctl);
+       if (err < 0)
+               return err;
        return 0;
 }
 EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
@@ -4028,9 +4046,9 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
 
        /* Search for codec ID */
        for (q = tbl; q->subvendor; q++) {
-               unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
-
-               if (vendorid == codec->subsystem_id)
+               unsigned int mask = 0xffff0000 | q->subdevice_mask;
+               unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask;
+               if ((codec->subsystem_id & mask) == id)
                        break;
        }
 
@@ -4752,6 +4770,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
        memset(sequences_hp, 0, sizeof(sequences_hp));
        assoc_line_out = 0;
 
+       codec->ignore_misc_bit = true;
        end_nid = codec->start_nid + codec->num_nodes;
        for (nid = codec->start_nid; nid < end_nid; nid++) {
                unsigned int wid_caps = get_wcaps(codec, nid);
@@ -4767,6 +4786,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
                        continue;
 
                def_conf = snd_hda_codec_get_pincfg(codec, nid);
+               if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+                     AC_DEFCFG_MISC_NO_PRESENCE))
+                       codec->ignore_misc_bit = false;
                conn = get_defcfg_connect(def_conf);
                if (conn == AC_JACK_PORT_NONE)
                        continue;
index 755f2b0f9d8e427b8401d4edb871ae5fa694411a..564471169cae72ada50a63e0f2e920964d60d107 100644 (file)
@@ -854,6 +854,7 @@ struct hda_codec {
        unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
        unsigned int pins_shutup:1;     /* pins are shut up */
        unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
+       unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int power_transition :1; /* power-state in transition */
index 1c8ddf547a2dde5b1426fdfb6d26261ea35e6872..c1da422e085a5230d8b7eb837925772b11ea4328 100644 (file)
@@ -297,10 +297,18 @@ static int hdmi_update_eld(struct hdmi_eld *e,
                                        buf + ELD_FIXED_BYTES + mnl + 3 * i);
        }
 
+       /*
+        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+        * in console or for audio devices. Assume the highest speakers
+        * configuration, to _not_ prohibit multi-channel audio playback.
+        */
+       if (!e->spk_alloc)
+               e->spk_alloc = 0xffff;
+
+       e->eld_valid = true;
        return 0;
 
 out_fail:
-       e->eld_ver = 0;
        return -EINVAL;
 }
 
@@ -323,9 +331,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
         * ELD is valid, actual eld_size is assigned in hdmi_update_eld()
         */
 
-       if (!eld->eld_valid)
-               return -ENOENT;
-
        size = snd_hdmi_get_eld_size(codec, nid);
        if (size == 0) {
                /* wfg: workaround for ASUS P5E-VM HDMI board */
@@ -342,18 +347,28 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
 
        for (i = 0; i < size; i++) {
                unsigned int val = hdmi_get_eld_data(codec, nid, i);
+               /*
+                * Graphics driver might be writing to ELD buffer right now.
+                * Just abort. The caller will repoll after a while.
+                */
                if (!(val & AC_ELDD_ELD_VALID)) {
-                       if (!i) {
-                               snd_printd(KERN_INFO
-                                          "HDMI: invalid ELD data\n");
-                               ret = -EINVAL;
-                               goto error;
-                       }
                        snd_printd(KERN_INFO
                                  "HDMI: invalid ELD data byte %d\n", i);
-                       val = 0;
-               } else
-                       val &= AC_ELDD_ELD_DATA;
+                       ret = -EINVAL;
+                       goto error;
+               }
+               val &= AC_ELDD_ELD_DATA;
+               /*
+                * The first byte cannot be zero. This can happen on some DVI
+                * connections. Some Intel chips may also need some 250ms delay
+                * to return non-zero ELD data, even when the graphics driver
+                * correctly writes ELD content before setting ELD_valid bit.
+                */
+               if (!val && !i) {
+                       snd_printdd(KERN_INFO "HDMI: 0 ELD data\n");
+                       ret = -EINVAL;
+                       goto error;
+               }
                buf[i] = val;
        }
 
index dcbea0da0fa2e5fea3681897cce0fe04e91ef3ef..618ddad172369b22062ad97114dd783841ccde43 100644 (file)
@@ -510,13 +510,15 @@ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
 
 static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
 {
-       return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) &&
-               /* disable MISC_NO_PRESENCE check because it may break too
-                * many devices
-                */
-               /*(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) &
-                 AC_DEFCFG_MISC_NO_PRESENCE)) &&*/
-               (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP);
+       if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
+               return false;
+       if (!codec->ignore_misc_bit &&
+           (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+            AC_DEFCFG_MISC_NO_PRESENCE))
+               return false;
+       if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+               return false;
+       return true;
 }
 
 /* flags for hda_nid_item */
@@ -651,6 +653,9 @@ struct hdmi_eld {
        int     spk_alloc;
        int     sad_count;
        struct cea_sad sad[ELD_MAX_SAD];
+       /*
+        * all fields above eld_buffer will be cleared before updating ELD
+        */
        char    eld_buffer[ELD_MAX_SIZE];
 #ifdef CONFIG_PROC_FS
        struct snd_info_entry *proc_entry;
index 2a2d8645ba0933e8e9e20ef3bd33a656f1bb69c5..70a7abda7e225744bf93d90f795c86bfcd95dac6 100644 (file)
@@ -58,6 +58,8 @@ struct cs_spec {
        unsigned int gpio_mask;
        unsigned int gpio_dir;
        unsigned int gpio_data;
+       unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */
+       unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */
 
        struct hda_pcm pcm_rec[2];      /* PCM information */
 
@@ -76,6 +78,7 @@ enum {
        CS420X_MBP53,
        CS420X_MBP55,
        CS420X_IMAC27,
+       CS420X_APPLE,
        CS420X_AUTO,
        CS420X_MODELS
 };
@@ -237,6 +240,15 @@ static int cs_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
        return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
 }
 
+static void cs_update_input_select(struct hda_codec *codec)
+{
+       struct cs_spec *spec = codec->spec;
+       if (spec->cur_adc)
+               snd_hda_codec_write(codec, spec->cur_adc, 0,
+                                   AC_VERB_SET_CONNECT_SEL,
+                                   spec->adc_idx[spec->cur_input]);
+}
+
 /*
  * Analog capture
  */
@@ -250,6 +262,7 @@ static int cs_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
        spec->cur_adc = spec->adc_nid[spec->cur_input];
        spec->cur_adc_stream_tag = stream_tag;
        spec->cur_adc_format = format;
+       cs_update_input_select(codec);
        snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
        return 0;
 }
@@ -689,10 +702,8 @@ static int change_cur_input(struct hda_codec *codec, unsigned int idx,
                                           spec->cur_adc_stream_tag, 0,
                                           spec->cur_adc_format);
        }
-       snd_hda_codec_write(codec, spec->cur_adc, 0,
-                           AC_VERB_SET_CONNECT_SEL,
-                           spec->adc_idx[idx]);
        spec->cur_input = idx;
+       cs_update_input_select(codec);
        return 1;
 }
 
@@ -920,10 +931,9 @@ static void cs_automute(struct hda_codec *codec)
                                        spdif_present ? 0 : PIN_OUT);
                }
        }
-       if (spec->board_config == CS420X_MBP53 ||
-           spec->board_config == CS420X_MBP55 ||
-           spec->board_config == CS420X_IMAC27) {
-               unsigned int gpio = hp_present ? 0x02 : 0x08;
+       if (spec->gpio_eapd_hp) {
+               unsigned int gpio = hp_present ?
+                       spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
                snd_hda_codec_write(codec, 0x01, 0,
                                    AC_VERB_SET_GPIO_DATA, gpio);
        }
@@ -973,10 +983,7 @@ static void cs_automic(struct hda_codec *codec)
                } else  {
                        spec->cur_input = spec->last_input;
                }
-
-               snd_hda_codec_write_cache(codec, spec->cur_adc, 0,
-                                       AC_VERB_SET_CONNECT_SEL,
-                                       spec->adc_idx[spec->cur_input]);
+               cs_update_input_select(codec);
        } else {
                if (present)
                        change_cur_input(codec, spec->automic_idx, 0);
@@ -1073,9 +1080,7 @@ static void init_input(struct hda_codec *codec)
                        cs_automic(codec);
                else  {
                        spec->cur_adc = spec->adc_nid[spec->cur_input];
-                       snd_hda_codec_write(codec, spec->cur_adc, 0,
-                                       AC_VERB_SET_CONNECT_SEL,
-                                       spec->adc_idx[spec->cur_input]);
+                       cs_update_input_select(codec);
                }
        } else {
                change_cur_input(codec, spec->cur_input, 1);
@@ -1273,6 +1278,7 @@ static const char * const cs420x_models[CS420X_MODELS] = {
        [CS420X_MBP53] = "mbp53",
        [CS420X_MBP55] = "mbp55",
        [CS420X_IMAC27] = "imac27",
+       [CS420X_APPLE] = "apple",
        [CS420X_AUTO] = "auto",
 };
 
@@ -1282,7 +1288,13 @@ static const struct snd_pci_quirk cs420x_cfg_tbl[] = {
        SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
        SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
        SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
-       SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
+       /* this conflicts with too many other models */
+       /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/
+       {} /* terminator */
+};
+
+static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = {
+       SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
        {} /* terminator */
 };
 
@@ -1364,6 +1376,10 @@ static int patch_cs420x(struct hda_codec *codec)
        spec->board_config =
                snd_hda_check_board_config(codec, CS420X_MODELS,
                                           cs420x_models, cs420x_cfg_tbl);
+       if (spec->board_config < 0)
+               spec->board_config =
+                       snd_hda_check_board_codec_sid_config(codec,
+                               CS420X_MODELS, NULL, cs420x_codec_cfg_tbl);
        if (spec->board_config >= 0)
                fix_pincfg(codec, spec->board_config, cs_pincfgs);
 
@@ -1371,10 +1387,11 @@ static int patch_cs420x(struct hda_codec *codec)
        case CS420X_IMAC27:
        case CS420X_MBP53:
        case CS420X_MBP55:
-               /* GPIO1 = headphones */
-               /* GPIO3 = speakers */
-               spec->gpio_mask = 0x0a;
-               spec->gpio_dir = 0x0a;
+       case CS420X_APPLE:
+               spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */
+               spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
+               spec->gpio_mask = spec->gpio_dir =
+                       spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
                break;
        }
 
index 5e706e4d17377434e83bf86ead1408e2494f5651..0de21193a2b025ba58363c0e2a509ec4545b495d 100644 (file)
@@ -3062,7 +3062,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS),
        SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
-       SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
                      CXT5066_LAPTOP),
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
index 81b7b791b3c36a09adef820b4ef4e5e837577121..c505fd5d338cc91d1de2199143c8141f24890355 100644 (file)
@@ -65,7 +65,11 @@ struct hdmi_spec_per_pin {
        hda_nid_t pin_nid;
        int num_mux_nids;
        hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
+
+       struct hda_codec *codec;
        struct hdmi_eld sink_eld;
+       struct delayed_work work;
+       int repoll_count;
 };
 
 struct hdmi_spec {
@@ -745,8 +749,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
  * Unsolicited events
  */
 
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
-                              struct hdmi_eld *eld);
+static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
 
 static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
 {
@@ -755,7 +758,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
        int pd = !!(res & AC_UNSOL_RES_PD);
        int eldv = !!(res & AC_UNSOL_RES_ELDV);
        int pin_idx;
-       struct hdmi_eld *eld;
 
        printk(KERN_INFO
                "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
@@ -764,17 +766,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
        pin_idx = pin_nid_to_pin_index(spec, pin_nid);
        if (pin_idx < 0)
                return;
-       eld = &spec->pins[pin_idx].sink_eld;
-
-       hdmi_present_sense(codec, pin_nid, eld);
 
-       /*
-        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-        * in console or for audio devices. Assume the highest speakers
-        * configuration, to _not_ prohibit multi-channel audio playback.
-        */
-       if (!eld->spk_alloc)
-               eld->spk_alloc = 0xffff;
+       hdmi_present_sense(&spec->pins[pin_idx], 1);
 }
 
 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -968,9 +961,11 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
        return 0;
 }
 
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
-                              struct hdmi_eld *eld)
+static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 {
+       struct hda_codec *codec = per_pin->codec;
+       struct hdmi_eld *eld = &per_pin->sink_eld;
+       hda_nid_t pin_nid = per_pin->pin_nid;
        /*
         * Always execute a GetPinSense verb here, even when called from
         * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited
@@ -980,26 +975,42 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
         * the unsolicited response to avoid custom WARs.
         */
        int present = snd_hda_pin_sense(codec, pin_nid);
+       bool eld_valid = false;
 
-       memset(eld, 0, sizeof(*eld));
+       memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer));
 
        eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
        if (eld->monitor_present)
-               eld->eld_valid  = !!(present & AC_PINSENSE_ELDV);
-       else
-               eld->eld_valid  = 0;
+               eld_valid       = !!(present & AC_PINSENSE_ELDV);
 
        printk(KERN_INFO
                "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-               codec->addr, pin_nid, eld->monitor_present, eld->eld_valid);
+               codec->addr, pin_nid, eld->monitor_present, eld_valid);
 
-       if (eld->eld_valid)
+       if (eld_valid) {
                if (!snd_hdmi_get_eld(eld, codec, pin_nid))
                        snd_hdmi_show_eld(eld);
+               else if (repoll) {
+                       queue_delayed_work(codec->bus->workq,
+                                          &per_pin->work,
+                                          msecs_to_jiffies(300));
+               }
+       }
 
        snd_hda_input_jack_report(codec, pin_nid);
 }
 
+static void hdmi_repoll_eld(struct work_struct *work)
+{
+       struct hdmi_spec_per_pin *per_pin =
+       container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work);
+
+       if (per_pin->repoll_count++ > 6)
+               per_pin->repoll_count = 0;
+
+       hdmi_present_sense(per_pin, per_pin->repoll_count);
+}
+
 static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
 {
        struct hdmi_spec *spec = codec->spec;
@@ -1228,7 +1239,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
        if (err < 0)
                return err;
 
-       hdmi_present_sense(codec, per_pin->pin_nid, &per_pin->sink_eld);
+       hdmi_present_sense(per_pin, 0);
        return 0;
 }
 
@@ -1279,6 +1290,8 @@ static int generic_hdmi_init(struct hda_codec *codec)
                                    AC_VERB_SET_UNSOLICITED_ENABLE,
                                    AC_USRSP_EN | pin_nid);
 
+               per_pin->codec = codec;
+               INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld);
                snd_hda_eld_proc_new(codec, eld, pin_idx);
        }
        return 0;
@@ -1293,10 +1306,12 @@ static void generic_hdmi_free(struct hda_codec *codec)
                struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
                struct hdmi_eld *eld = &per_pin->sink_eld;
 
+               cancel_delayed_work(&per_pin->work);
                snd_hda_eld_proc_free(codec, eld);
        }
        snd_hda_input_jack_free(codec);
 
+       flush_workqueue(codec->bus->workq);
        kfree(spec);
 }
 
index a24e068a021b1f1135bfe093ea350b5b66acf30b..cbde019d3d52b985e4c8a95b5f74386ac34eef69 100644 (file)
@@ -277,6 +277,12 @@ static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
        return false;
 }
 
+static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx)
+{
+       return spec->capsrc_nids ?
+               spec->capsrc_nids[idx] : spec->adc_nids[idx];
+}
+
 /* select the given imux item; either unmute exclusively or select the route */
 static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
                          unsigned int idx, bool force)
@@ -284,7 +290,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
        struct alc_spec *spec = codec->spec;
        const struct hda_input_mux *imux;
        unsigned int mux_idx;
-       int i, type;
+       int i, type, num_conns;
        hda_nid_t nid;
 
        mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
@@ -303,20 +309,20 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
                adc_idx = spec->dyn_adc_idx[idx];
        }
 
-       nid = spec->capsrc_nids ?
-               spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
+       nid = get_capsrc(spec, adc_idx);
 
        /* no selection? */
-       if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
+       num_conns = snd_hda_get_conn_list(codec, nid, NULL);
+       if (num_conns <= 1)
                return 1;
 
        type = get_wcaps_type(get_wcaps(codec, nid));
        if (type == AC_WID_AUD_MIX) {
                /* Matrix-mixer style (e.g. ALC882) */
-               for (i = 0; i < imux->num_items; i++) {
-                       unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
-                       snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
-                                                imux->items[i].index,
+               int active = imux->items[idx].index;
+               for (i = 0; i < num_conns; i++) {
+                       unsigned int v = (i == active) ? 0 : HDA_AMP_MUTE;
+                       snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, i,
                                                 HDA_AMP_MUTE, v);
                }
        } else {
@@ -1053,8 +1059,19 @@ static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
        spec->imux_pins[2] = spec->dock_mic_pin;
        for (i = 0; i < 3; i++) {
                strcpy(imux->items[i].label, texts[i]);
-               if (spec->imux_pins[i])
+               if (spec->imux_pins[i]) {
+                       hda_nid_t pin = spec->imux_pins[i];
+                       int c;
+                       for (c = 0; c < spec->num_adc_nids; c++) {
+                               hda_nid_t cap = get_capsrc(spec, c);
+                               int idx = get_connection_index(codec, cap, pin);
+                               if (idx >= 0) {
+                                       imux->items[i].index = idx;
+                                       break;
+                               }
+                       }
                        imux->num_items = i + 1;
+               }
        }
        spec->num_mux_defs = 1;
        spec->input_mux = imux;
@@ -1451,7 +1468,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)
                switch (fix->type) {
                case ALC_FIXUP_SKU:
                        if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
-                               break;;
+                               break;
                        snd_printdd(KERN_INFO "hda_codec: %s: "
                                    "Apply sku override for %s\n",
                                    codec->chip_name, modelname);
@@ -1956,10 +1973,8 @@ static int alc_build_controls(struct hda_codec *codec)
                if (!kctl)
                        kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
                for (i = 0; kctl && i < kctl->count; i++) {
-                       const hda_nid_t *nids = spec->capsrc_nids;
-                       if (!nids)
-                               nids = spec->adc_nids;
-                       err = snd_hda_add_nid(codec, kctl, i, nids[i]);
+                       err = snd_hda_add_nid(codec, kctl, i,
+                                             get_capsrc(spec, i));
                        if (err < 0)
                                return err;
                }
@@ -2746,8 +2761,7 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
                }
 
                for (c = 0; c < num_adcs; c++) {
-                       hda_nid_t cap = spec->capsrc_nids ?
-                               spec->capsrc_nids[c] : spec->adc_nids[c];
+                       hda_nid_t cap = get_capsrc(spec, c);
                        idx = get_connection_index(codec, cap, pin);
                        if (idx >= 0) {
                                spec->imux_pins[imux->num_items] = pin;
@@ -3693,8 +3707,7 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
        if (!pin)
                return 0;
        for (i = 0; i < spec->num_adc_nids; i++) {
-               hda_nid_t cap = spec->capsrc_nids ?
-                       spec->capsrc_nids[i] : spec->adc_nids[i];
+               hda_nid_t cap = get_capsrc(spec, i);
                int idx;
 
                idx = get_connection_index(codec, cap, pin);
index 4e715fefebefb1b0ae5c9e43fe73000447d11664..f3658658548e35179c70069cb31a498cabc155f7 100644 (file)
@@ -95,6 +95,7 @@ enum {
        STAC_92HD83XXX_REF,
        STAC_92HD83XXX_PWR_REF,
        STAC_DELL_S14,
+       STAC_DELL_VOSTRO_3500,
        STAC_92HD83XXX_HP,
        STAC_92HD83XXX_HP_cNB11_INTQUAD,
        STAC_HP_DV7_4000,
@@ -226,7 +227,6 @@ struct sigmatel_spec {
 
        /* power management */
        unsigned int num_pwrs;
-       const unsigned int *pwr_mapping;
        const hda_nid_t *pwr_nids;
        const hda_nid_t *dac_list;
 
@@ -373,18 +373,15 @@ static const unsigned long stac92hd73xx_capvols[] = {
 
 #define STAC92HD83_DAC_COUNT 3
 
-static const hda_nid_t stac92hd83xxx_pwr_nids[4] = {
-       0xa, 0xb, 0xd, 0xe,
+static const hda_nid_t stac92hd83xxx_pwr_nids[7] = {
+       0x0a, 0x0b, 0x0c, 0xd, 0x0e,
+       0x0f, 0x10
 };
 
 static const hda_nid_t stac92hd83xxx_slave_dig_outs[2] = {
        0x1e, 0,
 };
 
-static const unsigned int stac92hd83xxx_pwr_mapping[4] = {
-       0x03, 0x0c, 0x20, 0x40,
-};
-
 static const hda_nid_t stac92hd83xxx_dmic_nids[] = {
                0x11, 0x20,
 };
@@ -1644,6 +1641,8 @@ static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = {
                      "Alienware M17x", STAC_ALIENWARE_M17X),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a,
                      "Alienware M17x", STAC_ALIENWARE_M17X),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
+                     "Alienware M17x", STAC_ALIENWARE_M17X),
        {} /* terminator */
 };
 
@@ -1659,6 +1658,12 @@ static const unsigned int dell_s14_pin_configs[10] = {
        0x40f000f0, 0x40f000f0,
 };
 
+static const unsigned int dell_vostro_3500_pin_configs[10] = {
+       0x02a11020, 0x0221101f, 0x400000f0, 0x90170110,
+       0x400000f1, 0x400000f2, 0x400000f3, 0x90a60160,
+       0x400000f4, 0x400000f5,
+};
+
 static const unsigned int hp_dv7_4000_pin_configs[10] = {
        0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110,
        0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140,
@@ -1675,6 +1680,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
        [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
        [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
        [STAC_DELL_S14] = dell_s14_pin_configs,
+       [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs,
        [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs,
        [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs,
 };
@@ -1684,6 +1690,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
        [STAC_92HD83XXX_REF] = "ref",
        [STAC_92HD83XXX_PWR_REF] = "mic-ref",
        [STAC_DELL_S14] = "dell-s14",
+       [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500",
        [STAC_92HD83XXX_HP] = "hp",
        [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad",
        [STAC_HP_DV7_4000] = "hp-dv7-4000",
@@ -1697,6 +1704,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
                      "DFI LanParty", STAC_92HD83XXX_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
                      "unknown Dell", STAC_DELL_S14),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028,
+                     "Dell Vostro 3500", STAC_DELL_VOSTRO_3500),
        SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
                          "HP", STAC_92HD83XXX_HP),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,
@@ -4459,8 +4468,12 @@ static int stac92xx_init(struct hda_codec *codec)
                                stac_toggle_power_map(codec, nid, 1);
                        continue;
                }
-               if (enable_pin_detect(codec, nid, STAC_PWR_EVENT))
+               if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) {
                        stac_issue_unsol_event(codec, nid);
+                       continue;
+               }
+               /* none of the above, turn the port OFF */
+               stac_toggle_power_map(codec, nid, 0);
        }
 
        /* sync mute LED */
@@ -4716,11 +4729,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
        if (idx >= spec->num_pwrs)
                return;
 
-       /* several codecs have two power down bits */
-       if (spec->pwr_mapping)
-               idx = spec->pwr_mapping[idx];
-       else
-               idx = 1 << idx;
+       idx = 1 << idx;
 
        val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff;
        if (enable)
@@ -5618,9 +5627,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
                snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e);
        }
 
-       /* reset pin power-down; Windows may leave these bits after reboot */
-       snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0);
-       snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0);
        codec->no_trigger_sense = 1;
        codec->spec = spec;
 
@@ -5630,7 +5636,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
        spec->digbeep_nid = 0x21;
        spec->pwr_nids = stac92hd83xxx_pwr_nids;
-       spec->pwr_mapping = stac92hd83xxx_pwr_mapping;
        spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
        spec->multiout.dac_nids = spec->dac_nids;
        spec->init = stac92hd83xxx_core_init;
@@ -5647,9 +5652,6 @@ again:
                stac92xx_set_config_regs(codec,
                                stac92hd83xxx_brd_tbl[spec->board_config]);
 
-       if (spec->board_config != STAC_92HD83XXX_PWR_REF)
-               spec->num_pwrs = 0;
-
        codec->patch_ops = stac92xx_patch_ops;
 
        if (find_mute_led_gpio(codec, 0))
@@ -5858,8 +5860,6 @@ again:
                    (codec->revision_id & 0xf) == 1)
                        spec->stream_delay = 40; /* 40 milliseconds */
 
-               /* no output amps */
-               spec->num_pwrs = 0;
                /* disable VSW */
                spec->init = stac92hd71bxx_core_init;
                unmute_init++;
@@ -5874,8 +5874,6 @@ again:
                if ((codec->revision_id & 0xf) == 1)
                        spec->stream_delay = 40; /* 40 milliseconds */
 
-               /* no output amps */
-               spec->num_pwrs = 0;
                /* fallthru */
        default:
                spec->init = stac92hd71bxx_core_init;
index 431c0d417eeb61500c3332c687568a7851307201..b5137629f8e942a75a941e0e183cef98fb58db02 100644 (file)
@@ -208,6 +208,7 @@ struct via_spec {
        /* work to check hp jack state */
        struct hda_codec *codec;
        struct delayed_work vt1708_hp_work;
+       int hp_work_active;
        int vt1708_jack_detect;
        int vt1708_hp_present;
 
@@ -305,27 +306,35 @@ enum {
 static void analog_low_current_mode(struct hda_codec *codec);
 static bool is_aa_path_mute(struct hda_codec *codec);
 
-static void vt1708_start_hp_work(struct via_spec *spec)
+#define hp_detect_with_aa(codec) \
+       (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
+        !is_aa_path_mute(codec))
+
+static void vt1708_stop_hp_work(struct via_spec *spec)
 {
        if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
                return;
-       snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
-                           !spec->vt1708_jack_detect);
-       if (!delayed_work_pending(&spec->vt1708_hp_work))
-               schedule_delayed_work(&spec->vt1708_hp_work,
-                                     msecs_to_jiffies(100));
+       if (spec->hp_work_active) {
+               snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1);
+               cancel_delayed_work_sync(&spec->vt1708_hp_work);
+               spec->hp_work_active = 0;
+       }
 }
 
-static void vt1708_stop_hp_work(struct via_spec *spec)
+static void vt1708_update_hp_work(struct via_spec *spec)
 {
        if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
                return;
-       if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1
-           && !is_aa_path_mute(spec->codec))
-               return;
-       snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
-                           !spec->vt1708_jack_detect);
-       cancel_delayed_work_sync(&spec->vt1708_hp_work);
+       if (spec->vt1708_jack_detect &&
+           (spec->active_streams || hp_detect_with_aa(spec->codec))) {
+               if (!spec->hp_work_active) {
+                       snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0);
+                       schedule_delayed_work(&spec->vt1708_hp_work,
+                                             msecs_to_jiffies(100));
+                       spec->hp_work_active = 1;
+               }
+       } else if (!hp_detect_with_aa(spec->codec))
+               vt1708_stop_hp_work(spec);
 }
 
 static void set_widgets_power_state(struct hda_codec *codec)
@@ -343,12 +352,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
 
        set_widgets_power_state(codec);
        analog_low_current_mode(snd_kcontrol_chip(kcontrol));
-       if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
-               if (is_aa_path_mute(codec))
-                       vt1708_start_hp_work(codec->spec);
-               else
-                       vt1708_stop_hp_work(codec->spec);
-       }
+       vt1708_update_hp_work(codec->spec);
        return change;
 }
 
@@ -1154,7 +1158,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
        spec->cur_dac_stream_tag = stream_tag;
        spec->cur_dac_format = format;
        mutex_unlock(&spec->config_mutex);
-       vt1708_start_hp_work(spec);
+       vt1708_update_hp_work(spec);
        return 0;
 }
 
@@ -1174,7 +1178,7 @@ static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo,
        spec->cur_hp_stream_tag = stream_tag;
        spec->cur_hp_format = format;
        mutex_unlock(&spec->config_mutex);
-       vt1708_start_hp_work(spec);
+       vt1708_update_hp_work(spec);
        return 0;
 }
 
@@ -1188,7 +1192,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo,
        snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
        spec->active_streams &= ~STREAM_MULTI_OUT;
        mutex_unlock(&spec->config_mutex);
-       vt1708_stop_hp_work(spec);
+       vt1708_update_hp_work(spec);
        return 0;
 }
 
@@ -1203,7 +1207,7 @@ static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo,
                snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0);
        spec->active_streams &= ~STREAM_INDEP_HP;
        mutex_unlock(&spec->config_mutex);
-       vt1708_stop_hp_work(spec);
+       vt1708_update_hp_work(spec);
        return 0;
 }
 
@@ -1645,7 +1649,8 @@ static void via_hp_automute(struct hda_codec *codec)
        int nums;
        struct via_spec *spec = codec->spec;
 
-       if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0])
+       if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] &&
+           (spec->codec_type != VT1708 || spec->vt1708_jack_detect))
                present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
 
        if (spec->smart51_enabled)
@@ -2612,8 +2617,6 @@ static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
 
        if (spec->codec_type != VT1708)
                return 0;
-       spec->vt1708_jack_detect =
-               !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1);
        ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
        return 0;
 }
@@ -2623,18 +2626,22 @@ static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct via_spec *spec = codec->spec;
-       int change;
+       int val;
 
        if (spec->codec_type != VT1708)
                return 0;
-       spec->vt1708_jack_detect = ucontrol->value.integer.value[0];
-       change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8))
-               == !spec->vt1708_jack_detect;
-       if (spec->vt1708_jack_detect) {
+       val = !!ucontrol->value.integer.value[0];
+       if (spec->vt1708_jack_detect == val)
+               return 0;
+       spec->vt1708_jack_detect = val;
+       if (spec->vt1708_jack_detect &&
+           snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) {
                mute_aa_path(codec, 1);
                notify_aa_path_ctls(codec);
        }
-       return change;
+       via_hp_automute(codec);
+       vt1708_update_hp_work(spec);
+       return 1;
 }
 
 static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
@@ -2771,6 +2778,7 @@ static int via_init(struct hda_codec *codec)
        via_auto_init_unsol_event(codec);
 
        via_hp_automute(codec);
+       vt1708_update_hp_work(spec);
 
        return 0;
 }
@@ -2787,7 +2795,9 @@ static void vt1708_update_hp_jack_state(struct work_struct *work)
                spec->vt1708_hp_present ^= 1;
                via_hp_automute(spec->codec);
        }
-       vt1708_start_hp_work(spec);
+       if (spec->vt1708_jack_detect)
+               schedule_delayed_work(&spec->vt1708_hp_work,
+                                     msecs_to_jiffies(100));
 }
 
 static int get_mux_nids(struct hda_codec *codec)
index 29e312597f202b332f14a788889fa0c0d2a7f02a..11718b49b2e2459bb930384a4de50a34db6d54f8 100644 (file)
@@ -1077,6 +1077,13 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
                }
                if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV))
                        continue;
+
+               /* IO read operation is very expensive inside virtual machine
+                * as it is emulated. The probability that subsequent PICB read
+                * will return different result is high enough to loop till
+                * timeout here.
+                * Same CIV is strict enough condition to be sure that PICB
+                * is valid inside VM on emulated card. */
                if (chip->inside_vm)
                        break;
                if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
@@ -2930,6 +2937,45 @@ static unsigned int sis_codec_bits[3] = {
        ICH_PCR, ICH_SCR, ICH_SIS_TCR
 };
 
+static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci)
+{
+       int result  = inside_vm;
+       char *msg   = NULL;
+
+       /* check module parameter first (override detection) */
+       if (result >= 0) {
+               msg = result ? "enable (forced) VM" : "disable (forced) VM";
+               goto fini;
+       }
+
+       /* detect KVM and Parallels virtual environments */
+       result = kvm_para_available();
+#ifdef X86_FEATURE_HYPERVISOR
+       result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#endif
+       if (!result)
+               goto fini;
+
+       /* check for known (emulated) devices */
+       if (pci->subsystem_vendor == 0x1af4 &&
+           pci->subsystem_device == 0x1100) {
+               /* KVM emulated sound, PCI SSID: 1af4:1100 */
+               msg = "enable KVM";
+       } else if (pci->subsystem_vendor == 0x1ab8) {
+               /* Parallels VM emulated sound, PCI SSID: 1ab8:xxxx */
+               msg = "enable Parallels VM";
+       } else {
+               msg = "disable (unknown or VT-d) VM";
+               result = 0;
+       }
+
+fini:
+       if (msg != NULL)
+               printk(KERN_INFO "intel8x0: %s optimization\n", msg);
+
+       return result;
+}
+
 static int __devinit snd_intel8x0_create(struct snd_card *card,
                                         struct pci_dev *pci,
                                         unsigned long device_type,
@@ -2997,9 +3043,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
        if (xbox)
                chip->xbox = 1;
 
-       chip->inside_vm = inside_vm;
-       if (inside_vm)
-               printk(KERN_INFO "intel8x0: enable KVM optimization\n");
+       chip->inside_vm = snd_intel8x0_inside_vm(pci);
 
        if (pci->vendor == PCI_VENDOR_ID_INTEL &&
            pci->device == PCI_DEVICE_ID_INTEL_440MX)
@@ -3243,14 +3287,6 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
                        buggy_irq = 0;
        }
 
-       if (inside_vm < 0) {
-               /* detect KVM and Parallels virtual environments */
-               inside_vm = kvm_para_available();
-#if defined(__i386__) || defined(__x86_64__)
-               inside_vm = inside_vm || boot_cpu_has(X86_FEATURE_HYPERVISOR);
-#endif
-       }
-
        if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
                                       &chip)) < 0) {
                snd_card_free(card);
index 5c8717e29eebdbc4983933dcccaee36492457e41..8c3e7fcefd99c91c38d39f92fd0cae8323cee210 100644 (file)
@@ -78,10 +78,15 @@ unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port)
        return ioread32(address);
 }
 
-void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len)
+static void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data,
+                              u32 len)
 {
-       void __iomem *address = lx_dsp_register(chip, port);
-       memcpy_fromio(data, address, len*sizeof(u32));
+       u32 __iomem *address = lx_dsp_register(chip, port);
+       int i;
+
+       /* we cannot use memcpy_fromio */
+       for (i = 0; i != len; ++i)
+               data[i] = ioread32(address + i);
 }
 
 
@@ -91,11 +96,15 @@ void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data)
        iowrite32(data, address);
 }
 
-void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data,
-                        u32 len)
+static void lx_dsp_reg_writebuf(struct lx6464es *chip, int port,
+                               const u32 *data, u32 len)
 {
-       void __iomem *address = lx_dsp_register(chip, port);
-       memcpy_toio(address, data, len*sizeof(u32));
+       u32 __iomem *address = lx_dsp_register(chip, port);
+       int i;
+
+       /* we cannot use memcpy_to */
+       for (i = 0; i != len; ++i)
+               iowrite32(data[i], address + i);
 }
 
 
index 1dd562980b6c3595c233beffe49012c6352c605c..4d7ff797a6468abf5b5499cdfd92dab430d9948f 100644 (file)
@@ -72,10 +72,7 @@ enum {
 };
 
 unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port);
-void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len);
 void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data);
-void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data,
-                        u32 len);
 
 /* plx register access */
 enum {
index e760adad9523ebf82db4f07dbc259c73d8d44326..19ee2203cbb50fe7250bca2bad79c14e15a6069b 100644 (file)
@@ -6518,7 +6518,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
                        hdspm->io_type = AES32;
                        hdspm->card_name = "RME AES32";
                        hdspm->midiPorts = 2;
-               } else if ((hdspm->firmware_rev == 0xd5) ||
+               } else if ((hdspm->firmware_rev == 0xd2) ||
                        ((hdspm->firmware_rev >= 0xc8)  &&
                                (hdspm->firmware_rev <= 0xcf))) {
                        hdspm->io_type = MADI;
index a3ce1b22620dc45a27989c06f6eda5e44289704d..1aa52eff526a1d97094caa525681b25ca4c8d4e8 100644 (file)
@@ -876,7 +876,7 @@ static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
                (0x0fUL << 12) |
                (PS3_AUDIO_IOID);
 
-       ret = lv1_gpu_attribute(0x100, 0x007, val, 0, 0);
+       ret = lv1_gpu_attribute(0x100, 0x007, val);
        if (ret)
                pr_info("%s: gpu_attribute failed %d\n", __func__,
                        ret);
index 1ccf8dd47576ce4c746ffb54461c19f196acff43..45c63028b40d1636b56f6aa3e5f13e0d110b9a5d 100644 (file)
@@ -245,7 +245,7 @@ static const char *adau1373_bass_hpf_cutoff_text[] = {
 };
 
 static const unsigned int adau1373_bass_tlv[] = {
-       TLV_DB_RANGE_HEAD(4),
+       TLV_DB_RANGE_HEAD(3),
        0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1),
        3, 4, TLV_DB_SCALE_ITEM(950, 250, 0),
        5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0),
index 23d1bd5dadda36185e2c56702e7fd17a739f9a1a..69fde1506fe1fde2fe312ff80176723171ccef07 100644 (file)
@@ -434,7 +434,8 @@ static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
 {
        int ret;
        /* Set power-down bit */
-       ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN);
+       ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN,
+                                 CS4271_MODE2_PDN);
        if (ret < 0)
                return ret;
        return 0;
@@ -501,8 +502,9 @@ static int cs4271_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       ret = snd_soc_update_bits(codec, CS4271_MODE2, 0,
-               CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
+       ret = snd_soc_update_bits(codec, CS4271_MODE2,
+                                 CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
+                                 CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
        if (ret < 0)
                return ret;
        ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
index 27a078cbb6eb2542cb6bc0fa0be372b5a77cabac..4646e808b90a334e0d59935a1e93244672d276be 100644 (file)
@@ -177,7 +177,7 @@ static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0);
 static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
 /* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */
 static unsigned int mic_bst_tlv[] = {
-       TLV_DB_RANGE_HEAD(6),
+       TLV_DB_RANGE_HEAD(7),
        0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
        1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
        2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
index d15695d1c27397a7b3f2966c1806584e5e9a39bc..bbcf921166f7470fad24577d2aa52d1cf85258f4 100644 (file)
@@ -365,7 +365,7 @@ static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0);
 
 /* tlv for mic gain, 0db 20db 30db 40db */
 static const unsigned int mic_gain_tlv[] = {
-       TLV_DB_RANGE_HEAD(4),
+       TLV_DB_RANGE_HEAD(2),
        0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
        1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
 };
index bb82408ab8e1bb93f187dac610e5a1141501bd72..d2f37152f940cebc67f93a5bff140e64a67a07e7 100644 (file)
@@ -76,6 +76,8 @@ struct sta32x_priv {
 
        unsigned int mclk;
        unsigned int format;
+
+       u32 coef_shadow[STA32X_COEF_COUNT];
 };
 
 static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
@@ -227,6 +229,7 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
                                  struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
        int numcoef = kcontrol->private_value >> 16;
        int index = kcontrol->private_value & 0xffff;
        unsigned int cfud;
@@ -239,6 +242,11 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
        snd_soc_write(codec, STA32X_CFUD, cfud);
 
        snd_soc_write(codec, STA32X_CFADDR2, index);
+       for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++)
+               sta32x->coef_shadow[index + i] =
+                         (ucontrol->value.bytes.data[3 * i] << 16)
+                       | (ucontrol->value.bytes.data[3 * i + 1] << 8)
+                       | (ucontrol->value.bytes.data[3 * i + 2]);
        for (i = 0; i < 3 * numcoef; i++)
                snd_soc_write(codec, STA32X_B1CF1 + i,
                              ucontrol->value.bytes.data[i]);
@@ -252,6 +260,48 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
+{
+       struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+       unsigned int cfud;
+       int i;
+
+       /* preserve reserved bits in STA32X_CFUD */
+       cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
+
+       for (i = 0; i < STA32X_COEF_COUNT; i++) {
+               snd_soc_write(codec, STA32X_CFADDR2, i);
+               snd_soc_write(codec, STA32X_B1CF1,
+                             (sta32x->coef_shadow[i] >> 16) & 0xff);
+               snd_soc_write(codec, STA32X_B1CF2,
+                             (sta32x->coef_shadow[i] >> 8) & 0xff);
+               snd_soc_write(codec, STA32X_B1CF3,
+                             (sta32x->coef_shadow[i]) & 0xff);
+               /* chip documentation does not say if the bits are
+                * self-clearing, so do it explicitly */
+               snd_soc_write(codec, STA32X_CFUD, cfud);
+               snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
+       }
+       return 0;
+}
+
+int sta32x_cache_sync(struct snd_soc_codec *codec)
+{
+       unsigned int mute;
+       int rc;
+
+       if (!codec->cache_sync)
+               return 0;
+
+       /* mute during register sync */
+       mute = snd_soc_read(codec, STA32X_MMUTE);
+       snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
+       sta32x_sync_coef_shadow(codec);
+       rc = snd_soc_cache_sync(codec);
+       snd_soc_write(codec, STA32X_MMUTE, mute);
+       return rc;
+}
+
 #define SINGLE_COEF(xname, index) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = sta32x_coefficient_info, \
@@ -661,7 +711,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
                                return ret;
                        }
 
-                       snd_soc_cache_sync(codec);
+                       sta32x_cache_sync(codec);
                }
 
                /* Power up to mute */
@@ -790,6 +840,17 @@ static int sta32x_probe(struct snd_soc_codec *codec)
                            STA32X_CxCFG_OM_MASK,
                            2 << STA32X_CxCFG_OM_SHIFT);
 
+       /* initialize coefficient shadow RAM with reset values */
+       for (i = 4; i <= 49; i += 5)
+               sta32x->coef_shadow[i] = 0x400000;
+       for (i = 50; i <= 54; i++)
+               sta32x->coef_shadow[i] = 0x7fffff;
+       sta32x->coef_shadow[55] = 0x5a9df7;
+       sta32x->coef_shadow[56] = 0x7fffff;
+       sta32x->coef_shadow[59] = 0x7fffff;
+       sta32x->coef_shadow[60] = 0x400000;
+       sta32x->coef_shadow[61] = 0x400000;
+
        sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        /* Bias level configuration will have done an extra enable */
        regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
index b97ee5a75667399e77a5bcd7493432407d554cc2..d8e32a6262ee087ec13e73d24e57b936eefaa42b 100644 (file)
@@ -19,6 +19,7 @@
 /* STA326 register addresses */
 
 #define STA32X_REGISTER_COUNT  0x2d
+#define STA32X_COEF_COUNT 62
 
 #define STA32X_CONFA   0x00
 #define STA32X_CONFB    0x01
index 7e5ec03f6f8dd579d1bd43413fd1d007a1989bcb..a7c9ae17fc7eb0e743a8dbfb27db88fea58a456e 100644 (file)
@@ -453,6 +453,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
                snd_soc_write(codec, WM8731_PWR, 0xffff);
                regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
                                       wm8731->supplies);
+               codec->cache_sync = 1;
                break;
        }
        codec->dapm.bias_level = level;
index a9504710bb692e806655e785e5f35121ecf4afc1..3a629d0d690ed1fbe8129f096e0edf492faf9eb2 100644 (file)
@@ -190,6 +190,9 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
        u16 ioctl;
 
+       if (wm8753->dai_func == ucontrol->value.integer.value[0])
+               return 0;
+
        if (codec->active)
                return -EBUSY;
 
index 91d3c6dbeba3317758d747a6c6568cae625ea79e..53edd9a8c758f24943de1219b37cb45602fc11ef 100644 (file)
@@ -1973,7 +1973,7 @@ static int wm8962_reset(struct snd_soc_codec *codec)
 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
 static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0);
 static const unsigned int mixinpga_tlv[] = {
-       TLV_DB_RANGE_HEAD(7),
+       TLV_DB_RANGE_HEAD(5),
        0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
        2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0),
        3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0),
@@ -1988,7 +1988,7 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
 static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0);
 static const unsigned int classd_tlv[] = {
-       TLV_DB_RANGE_HEAD(7),
+       TLV_DB_RANGE_HEAD(2),
        0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
        7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
 };
index eec8e143511665a538c6950a4f679ad217aad827..d1a142f48b09f03fb565a5c4a6419842a854c6f6 100644 (file)
@@ -512,7 +512,7 @@ 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),
+       TLV_DB_RANGE_HEAD(2),
        0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
        3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
 };
index 6b73efd269917367293021edde0f330ee7c3b722..9c982e47eb99308b377e7143d8024c19863b14c5 100644 (file)
@@ -56,7 +56,7 @@ static int wm8994_retune_mobile_base[] = {
 static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994 *control = wm8994->control_data;
+       struct wm8994 *control = codec->control_data;
 
        switch (reg) {
        case WM8994_GPIO_1:
@@ -3030,19 +3030,34 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
 {
        struct wm8994_priv *wm8994 = data;
        struct snd_soc_codec *codec = wm8994->codec;
-       int reg;
+       int reg, count;
 
-       reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
-       if (reg < 0) {
-               dev_err(codec->dev, "Failed to read mic detect status: %d\n",
-                       reg);
-               return IRQ_NONE;
-       }
+       /* We may occasionally read a detection without an impedence
+        * range being provided - if that happens loop again.
+        */
+       count = 10;
+       do {
+               reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
+               if (reg < 0) {
+                       dev_err(codec->dev,
+                               "Failed to read mic detect status: %d\n",
+                               reg);
+                       return IRQ_NONE;
+               }
 
-       if (!(reg & WM8958_MICD_VALID)) {
-               dev_dbg(codec->dev, "Mic detect data not valid\n");
-               goto out;
-       }
+               if (!(reg & WM8958_MICD_VALID)) {
+                       dev_dbg(codec->dev, "Mic detect data not valid\n");
+                       goto out;
+               }
+
+               if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK))
+                       break;
+
+               msleep(1);
+       } while (count--);
+
+       if (count == 0)
+               dev_warn(codec->dev, "No impedence range reported for jack\n");
 
 #ifndef CONFIG_SND_SOC_WM8994_MODULE
        trace_snd_soc_jack_irq(dev_name(codec->dev));
@@ -3180,9 +3195,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
        wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
                           wm8994_fifo_error, "FIFO error", codec);
-       wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_WARN,
+       wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_WARN,
                           wm8994_temp_warn, "Thermal warning", codec);
-       wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_SHUT,
+       wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT,
                           wm8994_temp_shut, "Thermal shutdown", codec);
 
        ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
index 3cd35a02c28c7164f525f00f7375ac5ef4d6bbb1..4a398c3bfe84aea9ef4f6c8540f09b8b2bf34282 100644 (file)
@@ -807,7 +807,6 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
                        mdelay(100);
 
                        /* Normal bias enable & soft start off */
-                       reg |= WM9081_BIAS_ENA;
                        reg &= ~WM9081_VMID_RAMP;
                        snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
@@ -818,7 +817,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
                }
 
                /* VMID 2*240k */
-               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
+               reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
                reg &= ~WM9081_VMID_SEL_MASK;
                reg |= 0x04;
                snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
@@ -830,14 +829,15 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
                break;
 
        case SND_SOC_BIAS_OFF:
-               /* Startup bias source */
+               /* Startup bias source and disable bias */
                reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
                reg |= WM9081_BIAS_SRC;
+               reg &= ~WM9081_BIAS_ENA;
                snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
 
-               /* Disable VMID and biases with soft ramping */
+               /* Disable VMID with soft ramping */
                reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
-               reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
+               reg &= ~WM9081_VMID_SEL_MASK;
                reg |= WM9081_VMID_RAMP;
                snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
index 2b5252c9e37774963a55626e284878e7ff777414..f94c06057c64c31ac6e4bd70fbf80799cc52837d 100644 (file)
@@ -177,19 +177,19 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
 }
 
 static const unsigned int in_tlv[] = {
-       TLV_DB_RANGE_HEAD(6),
+       TLV_DB_RANGE_HEAD(3),
        0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0),
        1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0),
        4, 6, TLV_DB_SCALE_ITEM(600, 600, 0),
 };
 static const unsigned int mix_tlv[] = {
-       TLV_DB_RANGE_HEAD(4),
+       TLV_DB_RANGE_HEAD(2),
        0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0),
        3, 3, TLV_DB_SCALE_ITEM(0, 0, 0),
 };
 static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
 static const unsigned int spkboost_tlv[] = {
-       TLV_DB_RANGE_HEAD(7),
+       TLV_DB_RANGE_HEAD(2),
        0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
        7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
 };
index 84f33d4ea2cd5ec5461d0f8518c2462c3a58d544..48e61e912400fb2d2cca4ad74d9faf17a3075444 100644 (file)
@@ -40,7 +40,7 @@ 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),
+       TLV_DB_RANGE_HEAD(2),
        0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
        7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
 };
index 0268cf989736f303a224fbd26b0db2e8bf97f2ed..83c4bd5b2dd76bbf3f401c5a6bf0159d337f29b4 100644 (file)
@@ -694,6 +694,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
 
        /* Initialize the the device_attribute structure */
        dev_attr = &ssi_private->dev_attr;
+       sysfs_attr_init(&dev_attr->attr);
        dev_attr->attr.name = "statistics";
        dev_attr->attr.mode = S_IRUGO;
        dev_attr->show = fsl_sysfs_ssi_show;
index 76dc74d24fc2ff7b50b9665b7443c56372c70b7c..1ef697fe17317a6860bddf14982841440bdeb87c 100644 (file)
@@ -625,13 +625,6 @@ static int mxs_saif_probe(struct platform_device *pdev)
        if (pdev->id >= ARRAY_SIZE(mxs_saif))
                return -EINVAL;
 
-       pdata = pdev->dev.platform_data;
-       if (pdata && pdata->init) {
-               ret = pdata->init();
-               if (ret)
-                       return ret;
-       }
-
        saif = kzalloc(sizeof(*saif), GFP_KERNEL);
        if (!saif)
                return -ENOMEM;
@@ -639,12 +632,17 @@ static int mxs_saif_probe(struct platform_device *pdev)
        mxs_saif[pdev->id] = saif;
        saif->id = pdev->id;
 
-       saif->master_id = saif->id;
-       if (pdata && pdata->get_master_id) {
-               saif->master_id = pdata->get_master_id(saif->id);
+       pdata = pdev->dev.platform_data;
+       if (pdata && !pdata->master_mode) {
+               saif->master_id = pdata->master_id;
                if (saif->master_id < 0 ||
-                       saif->master_id >= ARRAY_SIZE(mxs_saif))
+                       saif->master_id >= ARRAY_SIZE(mxs_saif) ||
+                       saif->master_id == saif->id) {
+                       dev_err(&pdev->dev, "get wrong master id\n");
                        return -EINVAL;
+               }
+       } else {
+               saif->master_id = saif->id;
        }
 
        saif->clk = clk_get(&pdev->dev, NULL);
index 9c0edad90d8b4b3591c7c3a23f4c03b9e42594c1..a4e3237956e26dc499602f9b7397cf196c7ee5ec 100644 (file)
@@ -365,7 +365,8 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
        if (ret)
                goto out3;
 
-       mfp_set_groupg(nuc900_audio->dev); /* enbale ac97 multifunction pin*/
+       /* enbale ac97 multifunction pin */
+       mfp_set_groupg(nuc900_audio->dev, "nuc900-audio");
 
        return 0;
 
index 60f65ace7474ddfcdf538ba3624c61193c6808a7..ab23869c01bb6734073b65c6c397fe177224c217 100644 (file)
@@ -765,10 +765,61 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
  * interface to ALSA control for feature/mixer units
  */
 
+/* volume control quirks */
+static void volume_control_quirks(struct usb_mixer_elem_info *cval,
+                                 struct snd_kcontrol *kctl)
+{
+       switch (cval->mixer->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
+                                "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;
+
+       case USB_ID(0x046d, 0x0808):
+       case USB_ID(0x046d, 0x0809):
+       case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
+       case USB_ID(0x046d, 0x0991):
+       /* Most audio usb devices lie about volume resolution.
+        * Most Logitech webcams have res = 384.
+        * Proboly there is some logitech magic behind this number --fishor
+        */
+               if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+                       snd_printk(KERN_INFO
+                               "set resolution quirk: cval->res = 384\n");
+                       cval->res = 384;
+               }
+               break;
+
+       }
+}
+
 /*
  * retrieve the minimum and maximum values for the specified control
  */
-static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
+static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
+                                  int default_min, struct snd_kcontrol *kctl)
 {
        /* for failsafe */
        cval->min = default_min;
@@ -844,6 +895,9 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
                cval->initialized = 1;
        }
 
+       if (kctl)
+               volume_control_quirks(cval, kctl);
+
        /* USB descriptions contain the dB scale in 1/256 dB unit
         * while ALSA TLV contains in 1/100 dB unit
         */
@@ -864,6 +918,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
        return 0;
 }
 
+#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
 
 /* get a feature/mixer unit info */
 static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
@@ -882,7 +937,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
                uinfo->value.integer.max = 1;
        } else {
                if (!cval->initialized) {
-                       get_min_max(cval, 0);
+                       get_min_max_with_quirks(cval, 0, kcontrol);
                        if (cval->initialized && cval->dBmin >= cval->dBmax) {
                                kcontrol->vd[0].access &= 
                                        ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@@ -1045,9 +1100,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                cval->ch_readonly = readonly_mask;
        }
 
-       /* get min/max values */
-       get_min_max(cval, 0);
-
        /* if all channels in the mask are marked read-only, make the control
         * read-only. set_cur_mix_value() will check the mask again and won't
         * issue write commands to read-only channels. */
@@ -1069,6 +1121,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                len = snd_usb_copy_string_desc(state, nameid,
                                kctl->id.name, sizeof(kctl->id.name));
 
+       /* get min/max values */
+       get_min_max_with_quirks(cval, 0, kctl);
+
        switch (control) {
        case UAC_FU_MUTE:
        case UAC_FU_VOLUME:
@@ -1118,51 +1173,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                break;
        }
 
-       /* 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
-                                "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;
-
-       case USB_ID(0x046d, 0x0808):
-       case USB_ID(0x046d, 0x0809):
-       case USB_ID(0x046d, 0x0991):
-       /* Most audio usb devices lie about volume resolution.
-        * Most Logitech webcams have res = 384.
-        * Proboly there is some logitech magic behind this number --fishor
-        */
-               if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
-                       snd_printk(KERN_INFO
-                               "set resolution quirk: cval->res = 384\n");
-                       cval->res = 384;
-               }
-               break;
-
-       }
-
        range = (cval->max - cval->min) / cval->res;
        /* Are there devices with volume range more than 255? I use a bit more
         * to be sure. 384 is a resolution magic number found on Logitech
index 2e5bc73440262a14f3e34472516aedf31ff4981a..a3ddac0deffd1eba937932a55553466f32308065 100644 (file)
@@ -137,12 +137,12 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
                return -ENOMEM;
        }
        if (fp->nr_rates > 0) {
-               rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
+               rate_table = kmemdup(fp->rate_table,
+                                    sizeof(int) * fp->nr_rates, GFP_KERNEL);
                if (!rate_table) {
                        kfree(fp);
                        return -ENOMEM;
                }
-               memcpy(rate_table, fp->rate_table, sizeof(int) * fp->nr_rates);
                fp->rate_table = rate_table;
        }
 
@@ -224,10 +224,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
        if (altsd->bNumEndpoints != 1)
                return -ENXIO;
 
-       fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+       fp = kmemdup(&ua_format, sizeof(*fp), GFP_KERNEL);
        if (!fp)
                return -ENOMEM;
-       memcpy(fp, &ua_format, sizeof(*fp));
 
        fp->iface = altsd->bInterfaceNumber;
        fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
index f82480fa7f27988c48ba90e80e014b43de745f0e..6ab58cc99d53effeced21668df5605e634913e6b 100644 (file)
@@ -262,13 +262,16 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
 
 static void open_counters(struct perf_evlist *evlist)
 {
-       struct perf_evsel *pos;
+       struct perf_evsel *pos, *first;
 
        if (evlist->cpus->map[0] < 0)
                no_inherit = true;
 
+       first = list_entry(evlist->entries.next, struct perf_evsel, node);
+
        list_for_each_entry(pos, &evlist->entries, node) {
                struct perf_event_attr *attr = &pos->attr;
+               struct xyarray *group_fd = NULL;
                /*
                 * Check if parse_single_tracepoint_event has already asked for
                 * PERF_SAMPLE_TIME.
@@ -283,15 +286,19 @@ static void open_counters(struct perf_evlist *evlist)
                 */
                bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
 
+               if (group && pos != first)
+                       group_fd = first->fd;
+
                config_attr(pos, evlist);
 retry_sample_id:
                attr->sample_id_all = sample_id_all_avail ? 1 : 0;
 try_again:
-               if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
+               if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
+                                    group_fd) < 0) {
                        int err = errno;
 
                        if (err == EPERM || err == EACCES) {
-                               ui__warning_paranoid();
+                               ui__error_paranoid();
                                exit(EXIT_FAILURE);
                        } else if (err ==  ENODEV && cpu_list) {
                                die("No such device - did you specify"
index 7ce65f52415e0799f060d35d67290fac196dfb12..7d98676808d8722a39623de8983642f987cea7cc 100644 (file)
@@ -278,9 +278,14 @@ struct stats                       runtime_itlb_cache_stats[MAX_NR_CPUS];
 struct stats                   runtime_dtlb_cache_stats[MAX_NR_CPUS];
 struct stats                   walltime_nsecs_stats;
 
-static int create_perf_stat_counter(struct perf_evsel *evsel)
+static int create_perf_stat_counter(struct perf_evsel *evsel,
+                                   struct perf_evsel *first)
 {
        struct perf_event_attr *attr = &evsel->attr;
+       struct xyarray *group_fd = NULL;
+
+       if (group && evsel != first)
+               group_fd = first->fd;
 
        if (scale)
                attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -289,14 +294,15 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
        attr->inherit = !no_inherit;
 
        if (system_wide)
-               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, group);
-
+               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
+                                               group, group_fd);
        if (target_pid == -1 && target_tid == -1) {
                attr->disabled = 1;
                attr->enable_on_exec = 1;
        }
 
-       return perf_evsel__open_per_thread(evsel, evsel_list->threads, group);
+       return perf_evsel__open_per_thread(evsel, evsel_list->threads,
+                                          group, group_fd);
 }
 
 /*
@@ -396,7 +402,7 @@ static int read_counter(struct perf_evsel *counter)
 static int run_perf_stat(int argc __used, const char **argv)
 {
        unsigned long long t0, t1;
-       struct perf_evsel *counter;
+       struct perf_evsel *counter, *first;
        int status = 0;
        int child_ready_pipe[2], go_pipe[2];
        const bool forks = (argc > 0);
@@ -453,8 +459,10 @@ static int run_perf_stat(int argc __used, const char **argv)
                close(child_ready_pipe[0]);
        }
 
+       first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
+
        list_for_each_entry(counter, &evsel_list->entries, node) {
-               if (create_perf_stat_counter(counter) < 0) {
+               if (create_perf_stat_counter(counter, first) < 0) {
                        if (errno == EINVAL || errno == ENOSYS || errno == ENOENT) {
                                if (verbose)
                                        ui__warning("%s event is not supported by the kernel.\n",
index efe696f936e2de354d2263b62dfbf5c17bc910f1..831d1baeac370ebd330d0e6e970f025f34e76e44 100644 (file)
@@ -291,7 +291,7 @@ static int test__open_syscall_event(void)
                goto out_thread_map_delete;
        }
 
-       if (perf_evsel__open_per_thread(evsel, threads, false) < 0) {
+       if (perf_evsel__open_per_thread(evsel, threads, false, NULL) < 0) {
                pr_debug("failed to open counter: %s, "
                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                         strerror(errno));
@@ -366,7 +366,7 @@ static int test__open_syscall_event_on_all_cpus(void)
                goto out_thread_map_delete;
        }
 
-       if (perf_evsel__open(evsel, cpus, threads, false) < 0) {
+       if (perf_evsel__open(evsel, cpus, threads, false, NULL) < 0) {
                pr_debug("failed to open counter: %s, "
                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                         strerror(errno));
@@ -531,7 +531,7 @@ static int test__basic_mmap(void)
 
                perf_evlist__add(evlist, evsels[i]);
 
-               if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) {
+               if (perf_evsel__open(evsels[i], cpus, threads, false, NULL) < 0) {
                        pr_debug("failed to open counter: %s, "
                                 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                                 strerror(errno));
index 7a871714d44ed52866545a203421366855cb0b99..c9cdedb581348aa158677b28f6465734abcb50d4 100644 (file)
@@ -89,6 +89,7 @@ static bool                   vmlinux_warned;
 static bool                    inherit                         =  false;
 static int                     realtime_prio                   =      0;
 static bool                    group                           =  false;
+static bool                    sample_id_all_avail             =   true;
 static unsigned int            mmap_pages                      =    128;
 
 static bool                    dump_symtab                     =  false;
@@ -199,7 +200,8 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
        struct symbol *sym;
 
        if (he == NULL || he->ms.sym == NULL ||
-           (he != top.sym_filter_entry && use_browser != 1))
+           ((top.sym_filter_entry == NULL ||
+             top.sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1))
                return;
 
        sym = he->ms.sym;
@@ -289,11 +291,13 @@ static void print_sym_table(void)
 
        printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
 
-       if (top.total_lost_warned != top.session->hists.stats.total_lost) {
-               top.total_lost_warned = top.session->hists.stats.total_lost;
-               color_fprintf(stdout, PERF_COLOR_RED, "WARNING:");
-               printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n",
-                      top.total_lost_warned);
+       if (top.sym_evsel->hists.stats.nr_lost_warned !=
+           top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
+               top.sym_evsel->hists.stats.nr_lost_warned =
+                       top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
+               color_fprintf(stdout, PERF_COLOR_RED,
+                             "WARNING: LOST %d chunks, Check IO/CPU overload",
+                             top.sym_evsel->hists.stats.nr_lost_warned);
                ++printed;
        }
 
@@ -561,7 +565,6 @@ static void perf_top__sort_new_samples(void *arg)
        hists__decay_entries_threaded(&t->sym_evsel->hists,
                                      top.hide_user_symbols,
                                      top.hide_kernel_symbols);
-       hists__output_recalc_col_len(&t->sym_evsel->hists, winsize.ws_row - 3);
 }
 
 static void *display_thread_tui(void *arg __used)
@@ -671,6 +674,7 @@ static int symbol_filter(struct map *map __used, struct symbol *sym)
 }
 
 static void perf_event__process_sample(const union perf_event *event,
+                                      struct perf_evsel *evsel,
                                       struct perf_sample *sample,
                                       struct perf_session *session)
 {
@@ -770,12 +774,8 @@ static void perf_event__process_sample(const union perf_event *event,
        }
 
        if (al.sym == NULL || !al.sym->ignore) {
-               struct perf_evsel *evsel;
                struct hist_entry *he;
 
-               evsel = perf_evlist__id2evsel(top.evlist, sample->id);
-               assert(evsel != NULL);
-
                if ((sort__has_parent || symbol_conf.use_callchain) &&
                    sample->callchain) {
                        err = perf_session__resolve_callchain(session, al.thread,
@@ -807,6 +807,7 @@ static void perf_event__process_sample(const union perf_event *event,
 static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
 {
        struct perf_sample sample;
+       struct perf_evsel *evsel;
        union perf_event *event;
        int ret;
 
@@ -817,10 +818,16 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
                        continue;
                }
 
+               evsel = perf_evlist__id2evsel(self->evlist, sample.id);
+               assert(evsel != NULL);
+
                if (event->header.type == PERF_RECORD_SAMPLE)
-                       perf_event__process_sample(event, &sample, self);
-               else
+                       perf_event__process_sample(event, evsel, &sample, self);
+               else if (event->header.type < PERF_RECORD_MAX) {
+                       hists__inc_nr_events(&evsel->hists, event->header.type);
                        perf_event__process(event, &sample, self);
+               } else
+                       ++self->hists.stats.nr_unknown_events;
        }
 }
 
@@ -834,10 +841,16 @@ static void perf_session__mmap_read(struct perf_session *self)
 
 static void start_counters(struct perf_evlist *evlist)
 {
-       struct perf_evsel *counter;
+       struct perf_evsel *counter, *first;
+
+       first = list_entry(evlist->entries.next, struct perf_evsel, node);
 
        list_for_each_entry(counter, &evlist->entries, node) {
                struct perf_event_attr *attr = &counter->attr;
+               struct xyarray *group_fd = NULL;
+
+               if (group && counter != first)
+                       group_fd = first->fd;
 
                attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
 
@@ -858,14 +871,23 @@ static void start_counters(struct perf_evlist *evlist)
                attr->mmap = 1;
                attr->comm = 1;
                attr->inherit = inherit;
+retry_sample_id:
+               attr->sample_id_all = sample_id_all_avail ? 1 : 0;
 try_again:
                if (perf_evsel__open(counter, top.evlist->cpus,
-                                    top.evlist->threads, group) < 0) {
+                                    top.evlist->threads, group,
+                                    group_fd) < 0) {
                        int err = errno;
 
                        if (err == EPERM || err == EACCES) {
-                               ui__warning_paranoid();
+                               ui__error_paranoid();
                                goto out_err;
+                       } else if (err == EINVAL && sample_id_all_avail) {
+                               /*
+                                * Old kernel, no attr->sample_id_type_all field
+                                */
+                               sample_id_all_avail = false;
+                               goto retry_sample_id;
                        }
                        /*
                         * If it's cycles then fall back to hrtimer
index bc8f4773d4d85386d46057ed74718543b3c4b87b..119e996035c8f0e8ef529ba0e195f93f7cc79396 100644 (file)
@@ -310,9 +310,12 @@ fallback:
                }
                err = -ENOENT;
                dso->annotate_warned = 1;
-               pr_err("Can't annotate %s: No vmlinux file%s was found in the "
-                      "path.\nPlease use 'perf buildid-cache -av vmlinux' or "
-                      "--vmlinux vmlinux.\n",
+               pr_err("Can't annotate %s:\n\n"
+                      "No vmlinux file%s\nwas found in the path.\n\n"
+                      "Please use:\n\n"
+                      "  perf buildid-cache -av vmlinux\n\n"
+                      "or:\n\n"
+                      "  --vmlinux vmlinux",
                       sym->name, build_id_msg ?: "");
                goto out_free_filename;
        }
index 155749d74350a670c166ed14d7f8f4629e4bea23..26817daa2961b5dc3eb0f6181238dc707fa7bdc9 100644 (file)
@@ -47,19 +47,20 @@ int dump_printf(const char *fmt, ...)
 }
 
 #ifdef NO_NEWT_SUPPORT
-void ui__warning(const char *format, ...)
+int ui__warning(const char *format, ...)
 {
        va_list args;
 
        va_start(args, format);
        vfprintf(stderr, format, args);
        va_end(args);
+       return 0;
 }
 #endif
 
-void ui__warning_paranoid(void)
+int ui__error_paranoid(void)
 {
-       ui__warning("Permission error - are you root?\n"
+       return ui__error("Permission error - are you root?\n"
                    "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
                    " -1 - Not paranoid at all\n"
                    "  0 - Disallow raw tracepoint access for unpriv\n"
index fd53db47e3de1200ce0229629410b5d8006d1652..f2ce88d04f54be1cc71c0b5f9969070e9b2a61c3 100644 (file)
@@ -19,23 +19,18 @@ static inline int ui_helpline__show_help(const char *format __used, va_list ap _
        return 0;
 }
 
-static inline struct ui_progress *ui_progress__new(const char *title __used,
-                                                  u64 total __used)
-{
-       return (struct ui_progress *)1;
-}
-
-static inline void ui_progress__update(struct ui_progress *self __used,
-                                      u64 curr __used) {}
+static inline void ui_progress__update(u64 curr __used, u64 total __used,
+                                      const char *title __used) {}
 
-static inline void ui_progress__delete(struct ui_progress *self __used) {}
+#define ui__error(format, arg...) ui__warning(format, ##arg)
 #else
 extern char ui_helpline__last_msg[];
 int ui_helpline__show_help(const char *format, va_list ap);
 #include "ui/progress.h"
+int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
 #endif
 
-void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
-void ui__warning_paranoid(void);
+int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
+int ui__error_paranoid(void);
 
 #endif /* __PERF_DEBUG_H */
index 2f6bc89027da7eb78b349bb71aa7c4765cbd2c27..fbb4b4ab9cc6925a57017abc3087eab9b3b12ff4 100644 (file)
@@ -539,3 +539,33 @@ void perf_evlist__set_selected(struct perf_evlist *evlist,
 {
        evlist->selected = evsel;
 }
+
+int perf_evlist__open(struct perf_evlist *evlist, bool group)
+{
+       struct perf_evsel *evsel, *first;
+       int err, ncpus, nthreads;
+
+       first = list_entry(evlist->entries.next, struct perf_evsel, node);
+
+       list_for_each_entry(evsel, &evlist->entries, node) {
+               struct xyarray *group_fd = NULL;
+
+               if (group && evsel != first)
+                       group_fd = first->fd;
+
+               err = perf_evsel__open(evsel, evlist->cpus, evlist->threads,
+                                      group, group_fd);
+               if (err < 0)
+                       goto out_err;
+       }
+
+       return 0;
+out_err:
+       ncpus = evlist->cpus ? evlist->cpus->nr : 1;
+       nthreads = evlist->threads ? evlist->threads->nr : 1;
+
+       list_for_each_entry_reverse(evsel, &evlist->entries, node)
+               perf_evsel__close(evsel, ncpus, nthreads);
+
+       return err;
+}
index 6be71fc57794e0fe67a68c7ca20cd60482ba556c..1779ffef782824a7a5e8b8506abbc6bb30055c2b 100644 (file)
@@ -50,6 +50,8 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
 
 union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
 
+int perf_evlist__open(struct perf_evlist *evlist, bool group);
+
 int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
 int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
 void perf_evlist__munmap(struct perf_evlist *evlist);
index b46f6e4bff3c6b2d19786b52fef6a0feeb578216..e42626422587851b9c1b6e755dfdb09858640124 100644 (file)
@@ -16,6 +16,7 @@
 #include "thread_map.h"
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
 
 int __perf_evsel__sample_size(u64 sample_type)
 {
@@ -204,15 +205,16 @@ int __perf_evsel__read(struct perf_evsel *evsel,
 }
 
 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                             struct thread_map *threads, bool group)
+                             struct thread_map *threads, bool group,
+                             struct xyarray *group_fds)
 {
        int cpu, thread;
        unsigned long flags = 0;
-       int pid = -1;
+       int pid = -1, err;
 
        if (evsel->fd == NULL &&
            perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
-               return -1;
+               return -ENOMEM;
 
        if (evsel->cgrp) {
                flags = PERF_FLAG_PID_CGROUP;
@@ -220,7 +222,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
        }
 
        for (cpu = 0; cpu < cpus->nr; cpu++) {
-               int group_fd = -1;
+               int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
 
                for (thread = 0; thread < threads->nr; thread++) {
 
@@ -231,8 +233,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
                                                                     pid,
                                                                     cpus->map[cpu],
                                                                     group_fd, flags);
-                       if (FD(evsel, cpu, thread) < 0)
+                       if (FD(evsel, cpu, thread) < 0) {
+                               err = -errno;
                                goto out_close;
+                       }
 
                        if (group && group_fd == -1)
                                group_fd = FD(evsel, cpu, thread);
@@ -249,7 +253,17 @@ out_close:
                }
                thread = threads->nr;
        } while (--cpu >= 0);
-       return -1;
+       return err;
+}
+
+void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
+{
+       if (evsel->fd == NULL)
+               return;
+
+       perf_evsel__close_fd(evsel, ncpus, nthreads);
+       perf_evsel__free_fd(evsel);
+       evsel->fd = NULL;
 }
 
 static struct {
@@ -269,7 +283,8 @@ static struct {
 };
 
 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                    struct thread_map *threads, bool group)
+                    struct thread_map *threads, bool group,
+                    struct xyarray *group_fd)
 {
        if (cpus == NULL) {
                /* Work around old compiler warnings about strict aliasing */
@@ -279,19 +294,23 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
        if (threads == NULL)
                threads = &empty_thread_map.map;
 
-       return __perf_evsel__open(evsel, cpus, threads, group);
+       return __perf_evsel__open(evsel, cpus, threads, group, group_fd);
 }
 
 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
-                            struct cpu_map *cpus, bool group)
+                            struct cpu_map *cpus, bool group,
+                            struct xyarray *group_fd)
 {
-       return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group);
+       return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group,
+                                 group_fd);
 }
 
 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
-                               struct thread_map *threads, bool group)
+                               struct thread_map *threads, bool group,
+                               struct xyarray *group_fd)
 {
-       return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group);
+       return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group,
+                                 group_fd);
 }
 
 static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
index e9a31554e2658cf1ac50a0d476f428c691ed5482..b1d15e6f7ae32a4efc173ebd7779cd06bc02f41f 100644 (file)
@@ -82,11 +82,15 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 
 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
-                            struct cpu_map *cpus, bool group);
+                            struct cpu_map *cpus, bool group,
+                            struct xyarray *group_fds);
 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
-                               struct thread_map *threads, bool group);
+                               struct thread_map *threads, bool group,
+                               struct xyarray *group_fds);
 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                    struct thread_map *threads, bool group);
+                    struct thread_map *threads, bool group,
+                    struct xyarray *group_fds);
+void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
 
 #define perf_evsel__match(evsel, t, c)         \
        (evsel->attr.type == PERF_TYPE_##t &&   \
index 76c0b2c49eb82ce9a888189899d6ce053df6c0bd..bcd05d05b4f01969906efe3dbfcc899ccdea554a 100644 (file)
@@ -1,5 +1,6 @@
 #define _FILE_OFFSET_BITS 64
 
+#include "util.h"
 #include <sys/types.h>
 #include <byteswap.h>
 #include <unistd.h>
@@ -11,7 +12,6 @@
 
 #include "evlist.h"
 #include "evsel.h"
-#include "util.h"
 #include "header.h"
 #include "../perf.h"
 #include "trace-event.h"
index f6a993963a1e61ee8bd38532cfb530921dbe7cf9..a36a3fa81ffba45ea6602145530289c1c326acbc 100644 (file)
@@ -365,7 +365,6 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded)
 
        root = hists__get_rotate_entries_in(hists);
        next = rb_first(root);
-       hists->stats.total_period = 0;
 
        while (next) {
                n = rb_entry(next, struct hist_entry, rb_node_in);
@@ -379,7 +378,6 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded)
                         * been set by, say, the hist_browser.
                         */
                        hists__apply_filters(hists, n);
-                       hists__inc_nr_entries(hists, n);
                }
        }
 }
@@ -442,6 +440,7 @@ static void __hists__output_resort(struct hists *hists, bool threaded)
        hists->entries = RB_ROOT;
 
        hists->nr_entries = 0;
+       hists->stats.total_period = 0;
        hists__reset_col_len(hists);
 
        while (next) {
index ff93ddc91c5c4a1510ac2d2c3eb7fae25414f6ad..c86c1d27bd1eca09cef6c00949293a251b345ef9 100644 (file)
@@ -28,6 +28,7 @@ struct events_stats {
        u64 total_lost;
        u64 total_invalid_chains;
        u32 nr_events[PERF_RECORD_HEADER_MAX];
+       u32 nr_lost_warned;
        u32 nr_unknown_events;
        u32 nr_invalid_chains;
        u32 nr_unknown_id;
index 7624324efad4c78987b6bffb8c8aedbf246ea064..9dd47a4f2596d011847330f0f7db079c20c652d9 100644 (file)
@@ -623,7 +623,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
                cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
 
        evsel->attr.inherit = inherit;
-       if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
+       /*
+        * This will group just the fds for this single evsel, to group
+        * multiple events, use evlist.open().
+        */
+       if (perf_evsel__open(evsel, cpus, threads, group, NULL) < 0) {
                PyErr_SetFromErrno(PyExc_OSError);
                return NULL;
        }
@@ -814,6 +818,25 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
        return Py_None;
 }
 
+static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
+                                  PyObject *args, PyObject *kwargs)
+{
+       struct perf_evlist *evlist = &pevlist->evlist;
+       int group = 0;
+       static char *kwlist[] = { "group", NULL };
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group))
+               return NULL;
+
+       if (perf_evlist__open(evlist, group) < 0) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               return NULL;
+       }
+
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
 static PyMethodDef pyrf_evlist__methods[] = {
        {
                .ml_name  = "mmap",
@@ -821,6 +844,12 @@ static PyMethodDef pyrf_evlist__methods[] = {
                .ml_flags = METH_VARARGS | METH_KEYWORDS,
                .ml_doc   = PyDoc_STR("mmap the file descriptor table.")
        },
+       {
+               .ml_name  = "open",
+               .ml_meth  = (PyCFunction)pyrf_evlist__open,
+               .ml_flags = METH_VARARGS | METH_KEYWORDS,
+               .ml_doc   = PyDoc_STR("open the file descriptors.")
+       },
        {
                .ml_name  = "poll",
                .ml_meth  = (PyCFunction)pyrf_evlist__poll,
index 20e011c99a9459351f8741a418a4d630e334ac22..85c1e6b76f0a4bbdd3d2c5b9e0d7359733dbfda7 100644 (file)
@@ -502,6 +502,7 @@ static void flush_sample_queue(struct perf_session *s,
        struct perf_sample sample;
        u64 limit = os->next_flush;
        u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
+       unsigned idx = 0, progress_next = os->nr_samples / 16;
        int ret;
 
        if (!ops->ordered_samples || !limit)
@@ -521,6 +522,11 @@ static void flush_sample_queue(struct perf_session *s,
                os->last_flush = iter->timestamp;
                list_del(&iter->list);
                list_add(&iter->list, &os->sample_cache);
+               if (++idx >= progress_next) {
+                       progress_next += os->nr_samples / 16;
+                       ui_progress__update(idx, os->nr_samples,
+                                           "Processing time ordered events...");
+               }
        }
 
        if (list_empty(head)) {
@@ -529,6 +535,8 @@ static void flush_sample_queue(struct perf_session *s,
                os->last_sample =
                        list_entry(head->prev, struct sample_queue, list);
        }
+
+       os->nr_samples = 0;
 }
 
 /*
@@ -588,6 +596,7 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
        u64 timestamp = new->timestamp;
        struct list_head *p;
 
+       ++os->nr_samples;
        os->last_sample = new;
 
        if (!sample) {
@@ -738,10 +747,27 @@ static int perf_session_deliver_event(struct perf_session *session,
 
        dump_event(session, event, file_offset, sample);
 
+       evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+       if (evsel != NULL && event->header.type != PERF_RECORD_SAMPLE) {
+               /*
+                * XXX We're leaving PERF_RECORD_SAMPLE unnacounted here
+                * because the tools right now may apply filters, discarding
+                * some of the samples. For consistency, in the future we
+                * should have something like nr_filtered_samples and remove
+                * the sample->period from total_sample_period, etc, KISS for
+                * now tho.
+                *
+                * Also testing against NULL allows us to handle files without
+                * attr.sample_id_all and/or without PERF_SAMPLE_ID. In the
+                * future probably it'll be a good idea to restrict event
+                * processing via perf_session to files with both set.
+                */
+               hists__inc_nr_events(&evsel->hists, event->header.type);
+       }
+
        switch (event->header.type) {
        case PERF_RECORD_SAMPLE:
                dump_sample(session, event, sample);
-               evsel = perf_evlist__id2evsel(session->evlist, sample->id);
                if (evsel == NULL) {
                        ++session->hists.stats.nr_unknown_id;
                        return -1;
@@ -874,11 +900,11 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
                                            const struct perf_event_ops *ops)
 {
        if (ops->lost == perf_event__process_lost &&
-           session->hists.stats.total_lost != 0) {
-               ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64
-                           "!\n\nCheck IO/CPU overload!\n\n",
-                           session->hists.stats.total_period,
-                           session->hists.stats.total_lost);
+           session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
+               ui__warning("Processed %d events and lost %d chunks!\n\n"
+                           "Check IO/CPU overload!\n\n",
+                           session->hists.stats.nr_events[0],
+                           session->hists.stats.nr_events[PERF_RECORD_LOST]);
        }
 
        if (session->hists.stats.nr_unknown_events != 0) {
@@ -1012,7 +1038,6 @@ int __perf_session__process_events(struct perf_session *session,
 {
        u64 head, page_offset, file_offset, file_pos, progress_next;
        int err, mmap_prot, mmap_flags, map_idx = 0;
-       struct ui_progress *progress;
        size_t  page_size, mmap_size;
        char *buf, *mmaps[8];
        union perf_event *event;
@@ -1030,9 +1055,6 @@ int __perf_session__process_events(struct perf_session *session,
                file_size = data_offset + data_size;
 
        progress_next = file_size / 16;
-       progress = ui_progress__new("Processing events...", file_size);
-       if (progress == NULL)
-               return -1;
 
        mmap_size = session->mmap_window;
        if (mmap_size > file_size)
@@ -1095,7 +1117,8 @@ more:
 
        if (file_pos >= progress_next) {
                progress_next += file_size / 16;
-               ui_progress__update(progress, file_pos);
+               ui_progress__update(file_pos, file_size,
+                                   "Processing events...");
        }
 
        if (file_pos < file_size)
@@ -1106,7 +1129,6 @@ more:
        session->ordered_samples.next_flush = ULLONG_MAX;
        flush_sample_queue(session, ops);
 out_err:
-       ui_progress__delete(progress);
        perf_session__warn_about_errors(session, ops);
        perf_session_free_sample_buffers(session);
        return err;
index 514b06d41f05ef21ef1b1fefeeda9a14c1e06a76..6e393c98eb344f60dead2883e71fd4f2d13cbde3 100644 (file)
@@ -23,6 +23,7 @@ struct ordered_samples {
        struct sample_queue     *sample_buffer;
        struct sample_queue     *last_sample;
        int                     sample_buffer_idx;
+       unsigned int            nr_samples;
 };
 
 struct perf_session {
index 01d1057f3074ce59e92e03ed27876b851ad39fbc..3996509679589896cdfbd5a2a2b4e5df6d5cca4b 100644 (file)
@@ -19,7 +19,6 @@ struct perf_top {
        u64                kernel_samples, us_samples;
        u64                exact_samples;
        u64                guest_us_samples, guest_kernel_samples;
-       u64                total_lost_warned;
        int                print_entries, count_filter, delay_secs;
        int                freq;
        pid_t              target_pid, target_tid;
index 2d530cf74f435875e84d2f66485ea00b6794e91f..d2655f08bcc033d757ba5740b2ed238984062f40 100644 (file)
@@ -80,7 +80,7 @@ static void die(const char *fmt, ...)
        int ret = errno;
 
        if (errno)
-               perror("trace-cmd");
+               perror("perf");
        else
                ret = -1;
 
index 5359f371d30a355c4838e3db4e170ca5e6f359c0..556829124b0246fff72fe09ad96ceab35119037b 100644 (file)
@@ -4,6 +4,7 @@
 #include "libslang.h"
 #include <newt.h>
 #include "ui.h"
+#include "util.h"
 #include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/rbtree.h>
@@ -168,6 +169,59 @@ void ui_browser__refresh_dimensions(struct ui_browser *self)
        self->x = 0;
 }
 
+void ui_browser__handle_resize(struct ui_browser *browser)
+{
+       ui__refresh_dimensions(false);
+       ui_browser__show(browser, browser->title, ui_helpline__current);
+       ui_browser__refresh(browser);
+}
+
+int ui_browser__warning(struct ui_browser *browser, int timeout,
+                       const char *format, ...)
+{
+       va_list args;
+       char *text;
+       int key = 0, err;
+
+       va_start(args, format);
+       err = vasprintf(&text, format, args);
+       va_end(args);
+
+       if (err < 0) {
+               va_start(args, format);
+               ui_helpline__vpush(format, args);
+               va_end(args);
+       } else {
+               while ((key == ui__question_window("Warning!", text,
+                                                  "Press any key...",
+                                                  timeout)) == K_RESIZE)
+                       ui_browser__handle_resize(browser);
+               free(text);
+       }
+
+       return key;
+}
+
+int ui_browser__help_window(struct ui_browser *browser, const char *text)
+{
+       int key;
+
+       while ((key = ui__help_window(text)) == K_RESIZE)
+               ui_browser__handle_resize(browser);
+
+       return key;
+}
+
+bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text)
+{
+       int key;
+
+       while ((key = ui__dialog_yesno(text)) == K_RESIZE)
+               ui_browser__handle_resize(browser);
+
+       return key == K_ENTER || toupper(key) == 'Y';
+}
+
 void ui_browser__reset_index(struct ui_browser *self)
 {
        self->index = self->top_idx = 0;
@@ -230,13 +284,15 @@ static void ui_browser__scrollbar_set(struct ui_browser *browser)
                       (browser->nr_entries - 1));
        }
 
+       SLsmg_set_char_set(1);
+
        while (h < height) {
                ui_browser__gotorc(browser, row++, col);
-               SLsmg_set_char_set(1);
-               SLsmg_write_char(h == pct ? SLSMG_DIAMOND_CHAR : SLSMG_BOARD_CHAR);
-               SLsmg_set_char_set(0);
+               SLsmg_write_char(h == pct ? SLSMG_DIAMOND_CHAR : SLSMG_CKBRD_CHAR);
                ++h;
        }
+
+       SLsmg_set_char_set(0);
 }
 
 static int __ui_browser__refresh(struct ui_browser *browser)
@@ -291,53 +347,10 @@ void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
        browser->seek(browser, browser->top_idx, SEEK_SET);
 }
 
-static int ui__getch(int delay_secs)
-{
-       struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
-       fd_set read_set;
-       int err, key;
-
-       FD_ZERO(&read_set);
-       FD_SET(0, &read_set);
-
-       if (delay_secs) {
-               timeout.tv_sec = delay_secs;
-               timeout.tv_usec = 0;
-       }
-
-        err = select(1, &read_set, NULL, NULL, ptimeout);
-
-       if (err == 0)
-               return K_TIMER;
-
-       if (err == -1) {
-               if (errno == EINTR)
-                       return K_RESIZE;
-               return K_ERROR;
-       }
-
-       key = SLang_getkey();
-       if (key != K_ESC)
-               return key;
-
-       FD_ZERO(&read_set);
-       FD_SET(0, &read_set);
-       timeout.tv_sec = 0;
-       timeout.tv_usec = 20;
-        err = select(1, &read_set, NULL, NULL, &timeout);
-       if (err == 0)
-               return K_ESC;
-
-       SLang_ungetkey(key);
-       return SLkp_getkey();
-}
-
 int ui_browser__run(struct ui_browser *self, int delay_secs)
 {
        int err, key;
 
-       pthread__unblock_sigwinch();
-
        while (1) {
                off_t offset;
 
@@ -351,10 +364,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs)
                key = ui__getch(delay_secs);
 
                if (key == K_RESIZE) {
-                       pthread_mutex_lock(&ui__lock);
-                       SLtt_get_screen_size();
-                       SLsmg_reinit_smg();
-                       pthread_mutex_unlock(&ui__lock);
+                       ui__refresh_dimensions(false);
                        ui_browser__refresh_dimensions(self);
                        __ui_browser__show_title(self, self->title);
                        ui_helpline__puts(self->helpline);
@@ -533,6 +543,47 @@ static int ui_browser__color_config(const char *var, const char *value,
        return -1;
 }
 
+void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence)
+{
+       switch (whence) {
+       case SEEK_SET:
+               browser->top = browser->entries;
+               break;
+       case SEEK_CUR:
+               browser->top = browser->top + browser->top_idx + offset;
+               break;
+       case SEEK_END:
+               browser->top = browser->top + browser->nr_entries + offset;
+               break;
+       default:
+               return;
+       }
+}
+
+unsigned int ui_browser__argv_refresh(struct ui_browser *browser)
+{
+       unsigned int row = 0, idx = browser->top_idx;
+       char **pos;
+
+       if (browser->top == NULL)
+               browser->top = browser->entries;
+
+       pos = (char **)browser->top;
+       while (idx < browser->nr_entries) {
+               if (!browser->filter || !browser->filter(browser, *pos)) {
+                       ui_browser__gotorc(browser, row, 0);
+                       browser->write(browser, pos, row);
+                       if (++row == browser->height)
+                               break;
+               }
+
+               ++idx;
+               ++pos;
+       }
+
+       return row;
+}
+
 void ui_browser__init(void)
 {
        int i = 0;
index a2c707d33c5eb2f406615026621e811853864408..84d761b730c10d9d11b1db8d88bcf0afeacb47a8 100644 (file)
@@ -43,6 +43,15 @@ void ui_browser__hide(struct ui_browser *self);
 int ui_browser__refresh(struct ui_browser *self);
 int ui_browser__run(struct ui_browser *browser, int delay_secs);
 void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
+void ui_browser__handle_resize(struct ui_browser *browser);
+
+int ui_browser__warning(struct ui_browser *browser, int timeout,
+                       const char *format, ...);
+int ui_browser__help_window(struct ui_browser *browser, const char *text);
+bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
+
+void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
+unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
 
 void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
 unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
index 4e0cb7fea7d9b3fc3d993fb96fe6c5d03308228b..0575905d1205a24b5353b54c2f4c548e4cc6c2e4 100644 (file)
@@ -1,6 +1,9 @@
+#include "../../util.h"
 #include "../browser.h"
 #include "../helpline.h"
 #include "../libslang.h"
+#include "../ui.h"
+#include "../util.h"
 #include "../../annotate.h"
 #include "../../hist.h"
 #include "../../sort.h"
@@ -8,15 +11,6 @@
 #include <pthread.h>
 #include <newt.h>
 
-static void ui__error_window(const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
-       va_end(ap);
-}
-
 struct annotate_browser {
        struct ui_browser b;
        struct rb_root    entries;
@@ -400,7 +394,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
                return -1;
 
        if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) {
-               ui__error_window(ui_helpline__last_msg);
+               ui__error("%s", ui_helpline__last_msg);
                return -1;
        }
 
index 4663dcb2a19b56905d0c105a948178e6599fb3cd..d0c94b4596852d4f47ce266400ca3c7bb0013a96 100644 (file)
@@ -17,6 +17,7 @@
 #include "../browser.h"
 #include "../helpline.h"
 #include "../util.h"
+#include "../ui.h"
 #include "map.h"
 
 struct hist_browser {
@@ -294,6 +295,15 @@ static void hist_browser__set_folding(struct hist_browser *self, bool unfold)
        ui_browser__reset_index(&self->b);
 }
 
+static void ui_browser__warn_lost_events(struct ui_browser *browser)
+{
+       ui_browser__warning(browser, 4,
+               "Events are being lost, check IO/CPU overload!\n\n"
+               "You may want to run 'perf' using a RT scheduler policy:\n\n"
+               " perf top -r 80\n\n"
+               "Or reduce the sampling frequency.");
+}
+
 static int hist_browser__run(struct hist_browser *self, const char *ev_name,
                             void(*timer)(void *arg), void *arg, int delay_secs)
 {
@@ -314,12 +324,18 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name,
                key = ui_browser__run(&self->b, delay_secs);
 
                switch (key) {
-               case -1:
-                       /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
+               case K_TIMER:
                        timer(arg);
                        ui_browser__update_nr_entries(&self->b, self->hists->nr_entries);
-                       hists__browser_title(self->hists, title, sizeof(title),
-                                            ev_name);
+
+                       if (self->hists->stats.nr_lost_warned !=
+                           self->hists->stats.nr_events[PERF_RECORD_LOST]) {
+                               self->hists->stats.nr_lost_warned =
+                                       self->hists->stats.nr_events[PERF_RECORD_LOST];
+                               ui_browser__warn_lost_events(&self->b);
+                       }
+
+                       hists__browser_title(self->hists, title, sizeof(title), ev_name);
                        ui_browser__show_title(&self->b, title);
                        continue;
                case 'D': { /* Debug */
@@ -883,7 +899,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                        goto out_free_stack;
                case 'a':
                        if (!browser->has_symbols) {
-                               ui__warning(
+                               ui_browser__warning(&browser->b, delay_secs * 2,
                        "Annotation is only available for symbolic views, "
                        "include \"sym\" in --sort to use it.");
                                continue;
@@ -901,7 +917,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                case K_F1:
                case 'h':
                case '?':
-                       ui__help_window("h/?/F1        Show this window\n"
+                       ui_browser__help_window(&browser->b,
+                                       "h/?/F1        Show this window\n"
                                        "UP/DOWN/PGUP\n"
                                        "PGDN/SPACE    Navigate\n"
                                        "q/ESC/CTRL+C  Exit browser\n\n"
@@ -914,7 +931,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                                        "C             Collapse all callchains\n"
                                        "E             Expand all callchains\n"
                                        "d             Zoom into current DSO\n"
-                                       "t             Zoom into current Thread\n");
+                                       "t             Zoom into current Thread");
                        continue;
                case K_ENTER:
                case K_RIGHT:
@@ -940,7 +957,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                }
                case K_ESC:
                        if (!left_exits &&
-                           !ui__dialog_yesno("Do you really want to exit?"))
+                           !ui_browser__dialog_yesno(&browser->b,
+                                              "Do you really want to exit?"))
                                continue;
                        /* Fall thru */
                case 'q':
@@ -993,6 +1011,7 @@ add_exit_option:
 
                if (choice == annotate) {
                        struct hist_entry *he;
+                       int err;
 do_annotate:
                        he = hist_browser__selected_entry(browser);
                        if (he == NULL)
@@ -1001,10 +1020,12 @@ do_annotate:
                         * Don't let this be freed, say, by hists__decay_entry.
                         */
                        he->used = true;
-                       hist_entry__tui_annotate(he, evsel->idx, nr_events,
-                                                timer, arg, delay_secs);
+                       err = hist_entry__tui_annotate(he, evsel->idx, nr_events,
+                                                      timer, arg, delay_secs);
                        he->used = false;
                        ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
+                       if (err)
+                               ui_browser__handle_resize(&browser->b);
                } else if (choice == browse_map)
                        map__browse(browser->selection->map);
                else if (choice == zoom_dso) {
@@ -1056,6 +1077,7 @@ out:
 struct perf_evsel_menu {
        struct ui_browser b;
        struct perf_evsel *selection;
+       bool lost_events, lost_events_warned;
 };
 
 static void perf_evsel_menu__write(struct ui_browser *browser,
@@ -1068,14 +1090,29 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
        unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
        const char *ev_name = event_name(evsel);
        char bf[256], unit;
+       const char *warn = " ";
+       size_t printed;
 
        ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
                                                       HE_COLORSET_NORMAL);
 
        nr_events = convert_unit(nr_events, &unit);
-       snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
-                unit, unit == ' ' ? "" : " ", ev_name);
-       slsmg_write_nstring(bf, browser->width);
+       printed = snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
+                          unit, unit == ' ' ? "" : " ", ev_name);
+       slsmg_printf("%s", bf);
+
+       nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST];
+       if (nr_events != 0) {
+               menu->lost_events = true;
+               if (!current_entry)
+                       ui_browser__set_color(browser, HE_COLORSET_TOP);
+               nr_events = convert_unit(nr_events, &unit);
+               snprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!", nr_events,
+                        unit, unit == ' ' ? "" : " ");
+               warn = bf;
+       }
+
+       slsmg_write_nstring(warn, browser->width - printed);
 
        if (current_entry)
                menu->selection = evsel;
@@ -1100,6 +1137,11 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
                switch (key) {
                case K_TIMER:
                        timer(arg);
+
+                       if (!menu->lost_events_warned && menu->lost_events) {
+                               ui_browser__warn_lost_events(&menu->b);
+                               menu->lost_events_warned = true;
+                       }
                        continue;
                case K_RIGHT:
                case K_ENTER:
@@ -1133,7 +1175,8 @@ browse_hists:
                                        pos = list_entry(pos->node.prev, struct perf_evsel, node);
                                goto browse_hists;
                        case K_ESC:
-                               if (!ui__dialog_yesno("Do you really want to exit?"))
+                               if (!ui_browser__dialog_yesno(&menu->b,
+                                               "Do you really want to exit?"))
                                        continue;
                                /* Fall thru */
                        case 'q':
@@ -1145,7 +1188,8 @@ browse_hists:
                case K_LEFT:
                        continue;
                case K_ESC:
-                       if (!ui__dialog_yesno("Do you really want to exit?"))
+                       if (!ui_browser__dialog_yesno(&menu->b,
+                                              "Do you really want to exit?"))
                                continue;
                        /* Fall thru */
                case 'q':
index f36d2ff509ed285baa5290d6780b3e9d8ca4ae9e..6ef3c56917626a38d835491d82461219b7dddf88 100644 (file)
@@ -1,20 +1,28 @@
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
-#include <newt.h>
+#include <string.h>
 
 #include "../debug.h"
 #include "helpline.h"
 #include "ui.h"
+#include "libslang.h"
 
 void ui_helpline__pop(void)
 {
-       newtPopHelpLine();
 }
 
+char ui_helpline__current[512];
+
 void ui_helpline__push(const char *msg)
 {
-       newtPushHelpLine(msg);
+       const size_t sz = sizeof(ui_helpline__current);
+
+       SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
+       SLsmg_set_color(0);
+       SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols);
+       SLsmg_refresh();
+       strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0';
 }
 
 void ui_helpline__vpush(const char *fmt, va_list ap)
@@ -63,7 +71,7 @@ int ui_helpline__show_help(const char *format, va_list ap)
 
        if (ui_helpline__last_msg[backlog - 1] == '\n') {
                ui_helpline__puts(ui_helpline__last_msg);
-               newtRefresh();
+               SLsmg_refresh();
                backlog = 0;
        }
        pthread_mutex_unlock(&ui__lock);
index fdcbc0270acd3bec570c0d1ac1953f06137442bb..7bab6b34e35ee7b9869c372373926e2f89d4dd57 100644 (file)
@@ -11,4 +11,6 @@ void ui_helpline__vpush(const char *fmt, va_list ap);
 void ui_helpline__fpush(const char *fmt, ...);
 void ui_helpline__puts(const char *msg);
 
+extern char ui_helpline__current[];
+
 #endif /* _PERF_UI_HELPLINE_H_ */
index d7fc399d36b30767ac5d1495597c0c8d9ec05d46..295e366b631100d1f871e36206395916680c2f21 100644 (file)
@@ -1,60 +1,29 @@
-#include <stdlib.h>
-#include <newt.h>
 #include "../cache.h"
 #include "progress.h"
+#include "libslang.h"
+#include "ui.h"
+#include "browser.h"
 
-struct ui_progress {
-       newtComponent form, scale;
-};
-
-struct ui_progress *ui_progress__new(const char *title, u64 total)
-{
-       struct ui_progress *self = malloc(sizeof(*self));
-
-       if (self != NULL) {
-               int cols;
-
-               if (use_browser <= 0)
-                       return self;
-               newtGetScreenSize(&cols, NULL);
-               cols -= 4;
-               newtCenteredWindow(cols, 1, title);
-               self->form  = newtForm(NULL, NULL, 0);
-               if (self->form == NULL)
-                       goto out_free_self;
-               self->scale = newtScale(0, 0, cols, total);
-               if (self->scale == NULL)
-                       goto out_free_form;
-               newtFormAddComponent(self->form, self->scale);
-               newtRefresh();
-       }
-
-       return self;
-
-out_free_form:
-       newtFormDestroy(self->form);
-out_free_self:
-       free(self);
-       return NULL;
-}
-
-void ui_progress__update(struct ui_progress *self, u64 curr)
+void ui_progress__update(u64 curr, u64 total, const char *title)
 {
+       int bar, y;
        /*
         * FIXME: We should have a per UI backend way of showing progress,
         * stdio will just show a percentage as NN%, etc.
         */
        if (use_browser <= 0)
                return;
-       newtScaleSet(self->scale, curr);
-       newtRefresh();
-}
 
-void ui_progress__delete(struct ui_progress *self)
-{
-       if (use_browser > 0) {
-               newtFormDestroy(self->form);
-               newtPopWindow();
-       }
-       free(self);
+       ui__refresh_dimensions(true);
+       pthread_mutex_lock(&ui__lock);
+       y = SLtt_Screen_Rows / 2 - 2;
+       SLsmg_set_color(0);
+       SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
+       SLsmg_gotorc(y++, 1);
+       SLsmg_write_string((char *)title);
+       SLsmg_set_color(HE_COLORSET_SELECTED);
+       bar = ((SLtt_Screen_Cols - 2) * curr) / total;
+       SLsmg_fill_region(y, 1, 1, bar, ' ');
+       SLsmg_refresh();
+       pthread_mutex_unlock(&ui__lock);
 }
index a3820a0beb5beb46adf1fe69cbcee0687ae5cbe8..d9c205b59aa1fca489350aec25dba6406c11fa52 100644 (file)
@@ -1,11 +1,8 @@
 #ifndef _PERF_UI_PROGRESS_H_
 #define _PERF_UI_PROGRESS_H_ 1
 
-struct ui_progress;
+#include <../types.h>
 
-struct ui_progress *ui_progress__new(const char *title, u64 total);
-void ui_progress__delete(struct ui_progress *self);
-
-void ui_progress__update(struct ui_progress *self, u64 curr);
+void ui_progress__update(u64 curr, u64 total, const char *title);
 
 #endif
index 1e6ba06980c4093248915077bdeb437d05098feb..85a69faa09aa6af44799795bf0e081093b1e536b 100644 (file)
@@ -7,10 +7,85 @@
 #include "browser.h"
 #include "helpline.h"
 #include "ui.h"
+#include "util.h"
 #include "libslang.h"
+#include "keysyms.h"
 
 pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
 
+static volatile int ui__need_resize;
+
+void ui__refresh_dimensions(bool force)
+{
+       if (force || ui__need_resize) {
+               ui__need_resize = 0;
+               pthread_mutex_lock(&ui__lock);
+               SLtt_get_screen_size();
+               SLsmg_reinit_smg();
+               pthread_mutex_unlock(&ui__lock);
+       }
+}
+
+static void ui__sigwinch(int sig __used)
+{
+       ui__need_resize = 1;
+}
+
+static void ui__setup_sigwinch(void)
+{
+       static bool done;
+
+       if (done)
+               return;
+
+       done = true;
+       pthread__unblock_sigwinch();
+       signal(SIGWINCH, ui__sigwinch);
+}
+
+int ui__getch(int delay_secs)
+{
+       struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
+       fd_set read_set;
+       int err, key;
+
+       ui__setup_sigwinch();
+
+       FD_ZERO(&read_set);
+       FD_SET(0, &read_set);
+
+       if (delay_secs) {
+               timeout.tv_sec = delay_secs;
+               timeout.tv_usec = 0;
+       }
+
+        err = select(1, &read_set, NULL, NULL, ptimeout);
+
+       if (err == 0)
+               return K_TIMER;
+
+       if (err == -1) {
+               if (errno == EINTR)
+                       return K_RESIZE;
+               return K_ERROR;
+       }
+
+       key = SLang_getkey();
+       if (key != K_ESC)
+               return key;
+
+       FD_ZERO(&read_set);
+       FD_SET(0, &read_set);
+       timeout.tv_sec = 0;
+       timeout.tv_usec = 20;
+        err = select(1, &read_set, NULL, NULL, &timeout);
+       if (err == 0)
+               return K_ESC;
+
+       SLang_ungetkey(key);
+       return SLkp_getkey();
+}
+
 static void newt_suspend(void *d __used)
 {
        newtSuspend();
@@ -71,10 +146,10 @@ void setup_browser(bool fallback_to_pager)
 void exit_browser(bool wait_for_ok)
 {
        if (use_browser > 0) {
-               if (wait_for_ok) {
-                       char title[] = "Fatal Error", ok[] = "Ok";
-                       newtWinMessage(title, ok, ui_helpline__last_msg);
-               }
+               if (wait_for_ok)
+                       ui__question_window("Fatal Error",
+                                           ui_helpline__last_msg,
+                                           "Press any key...", 0);
                ui__exit();
        }
 }
index d264e059c82996b83faa577313b3aec072786bdb..7b67045479f6034c084574e31af34955a5c64a4c 100644 (file)
@@ -2,7 +2,10 @@
 #define _PERF_UI_H_ 1
 
 #include <pthread.h>
+#include <stdbool.h>
 
 extern pthread_mutex_t ui__lock;
 
+void ui__refresh_dimensions(bool force);
+
 #endif /* _PERF_UI_H_ */
index fdf1fc8f08bc83b2300311870f9b68ee559ef7c6..45daa7c41dad9812226ba8737a23664709d50cbb 100644 (file)
@@ -1,6 +1,5 @@
-#include <newt.h>
+#include "../util.h"
 #include <signal.h>
-#include <stdio.h>
 #include <stdbool.h>
 #include <string.h>
 #include <sys/ttydefaults.h>
@@ -8,72 +7,75 @@
 #include "../cache.h"
 #include "../debug.h"
 #include "browser.h"
+#include "keysyms.h"
 #include "helpline.h"
 #include "ui.h"
 #include "util.h"
+#include "libslang.h"
 
-static void newt_form__set_exit_keys(newtComponent self)
+static void ui_browser__argv_write(struct ui_browser *browser,
+                                  void *entry, int row)
 {
-       newtFormAddHotKey(self, NEWT_KEY_LEFT);
-       newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
-       newtFormAddHotKey(self, 'Q');
-       newtFormAddHotKey(self, 'q');
-       newtFormAddHotKey(self, CTRL('c'));
-}
+       char **arg = entry;
+       bool current_entry = ui_browser__is_current_entry(browser, row);
 
-static newtComponent newt_form__new(void)
-{
-       newtComponent self = newtForm(NULL, NULL, 0);
-       if (self)
-               newt_form__set_exit_keys(self);
-       return self;
+       ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+                                                      HE_COLORSET_NORMAL);
+       slsmg_write_nstring(*arg, browser->width);
 }
 
-int ui__popup_menu(int argc, char * const argv[])
+static int popup_menu__run(struct ui_browser *menu)
 {
-       struct newtExitStruct es;
-       int i, rc = -1, max_len = 5;
-       newtComponent listbox, form = newt_form__new();
+       int key;
 
-       if (form == NULL)
+       if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
                return -1;
 
-       listbox = newtListbox(0, 0, argc, NEWT_FLAG_RETURNEXIT);
-       if (listbox == NULL)
-               goto out_destroy_form;
+       while (1) {
+               key = ui_browser__run(menu, 0);
 
-       newtFormAddComponent(form, listbox);
+               switch (key) {
+               case K_RIGHT:
+               case K_ENTER:
+                       key = menu->index;
+                       break;
+               case K_LEFT:
+               case K_ESC:
+               case 'q':
+               case CTRL('c'):
+                       key = -1;
+                       break;
+               default:
+                       continue;
+               }
 
-       for (i = 0; i < argc; ++i) {
-               int len = strlen(argv[i]);
-               if (len > max_len)
-                       max_len = len;
-               if (newtListboxAddEntry(listbox, argv[i], (void *)(long)i))
-                       goto out_destroy_form;
+               break;
        }
 
-       newtCenteredWindow(max_len, argc, NULL);
-       newtFormRun(form, &es);
-       rc = newtListboxGetCurrent(listbox) - NULL;
-       if (es.reason == NEWT_EXIT_HOTKEY)
-               rc = -1;
-       newtPopWindow();
-out_destroy_form:
-       newtFormDestroy(form);
-       return rc;
+       ui_browser__hide(menu);
+       return key;
 }
 
-int ui__help_window(const char *text)
+int ui__popup_menu(int argc, char * const argv[])
 {
-       struct newtExitStruct es;
-       newtComponent tb, form = newt_form__new();
-       int rc = -1;
+       struct ui_browser menu = {
+               .entries    = (void *)argv,
+               .refresh    = ui_browser__argv_refresh,
+               .seek       = ui_browser__argv_seek,
+               .write      = ui_browser__argv_write,
+               .nr_entries = argc,
+       };
+
+       return popup_menu__run(&menu);
+}
+
+int ui__question_window(const char *title, const char *text,
+                       const char *exit_msg, int delay_secs)
+{
+       int x, y;
        int max_len = 0, nr_lines = 0;
        const char *t;
 
-       if (form == NULL)
-               return -1;
-
        t = text;
        while (1) {
                const char *sep = strchr(t, '\n');
@@ -90,41 +92,77 @@ int ui__help_window(const char *text)
                t = sep + 1;
        }
 
-       tb = newtTextbox(0, 0, max_len, nr_lines, 0);
-       if (tb == NULL)
-               goto out_destroy_form;
-
-       newtTextboxSetText(tb, text);
-       newtFormAddComponent(form, tb);
-       newtCenteredWindow(max_len, nr_lines, NULL);
-       newtFormRun(form, &es);
-       newtPopWindow();
-       rc = 0;
-out_destroy_form:
-       newtFormDestroy(form);
-       return rc;
+       max_len += 2;
+       nr_lines += 4;
+       y = SLtt_Screen_Rows / 2 - nr_lines / 2,
+       x = SLtt_Screen_Cols / 2 - max_len / 2;
+
+       SLsmg_set_color(0);
+       SLsmg_draw_box(y, x++, nr_lines, max_len);
+       if (title) {
+               SLsmg_gotorc(y, x + 1);
+               SLsmg_write_string((char *)title);
+       }
+       SLsmg_gotorc(++y, x);
+       nr_lines -= 2;
+       max_len -= 2;
+       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
+                                  nr_lines, max_len, 1);
+       SLsmg_gotorc(y + nr_lines - 2, x);
+       SLsmg_write_nstring((char *)" ", max_len);
+       SLsmg_gotorc(y + nr_lines - 1, x);
+       SLsmg_write_nstring((char *)exit_msg, max_len);
+       SLsmg_refresh();
+       return ui__getch(delay_secs);
 }
 
-static const char yes[] = "Yes", no[] = "No",
-                 warning_str[] = "Warning!", ok[] = "Ok";
+int ui__help_window(const char *text)
+{
+       return ui__question_window("Help", text, "Press any key...", 0);
+}
 
-bool ui__dialog_yesno(const char *msg)
+int ui__dialog_yesno(const char *msg)
 {
-       /* newtWinChoice should really be accepting const char pointers... */
-       return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1;
+       return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
 }
 
-void ui__warning(const char *format, ...)
+int __ui__warning(const char *title, const char *format, va_list args)
 {
-       va_list args;
+       char *s;
+
+       if (use_browser > 0 && vasprintf(&s, format, args) > 0) {
+               int key;
 
-       va_start(args, format);
-       if (use_browser > 0) {
                pthread_mutex_lock(&ui__lock);
-               newtWinMessagev((char *)warning_str, (char *)ok,
-                               (char *)format, args);
+               key = ui__question_window(title, s, "Press any key...", 0);
                pthread_mutex_unlock(&ui__lock);
-       } else
-               vfprintf(stderr, format, args);
+               free(s);
+               return key;
+       }
+
+       fprintf(stderr, "%s:\n", title);
+       vfprintf(stderr, format, args);
+       return K_ESC;
+}
+
+int ui__warning(const char *format, ...)
+{
+       int key;
+       va_list args;
+
+       va_start(args, format);
+       key = __ui__warning("Warning", format, args);
+       va_end(args);
+       return key;
+}
+
+int ui__error(const char *format, ...)
+{
+       int key;
+       va_list args;
+
+       va_start(args, format);
+       key = __ui__warning("Error", format, args);
        va_end(args);
+       return key;
 }
index afcbc1d99531595eee370f9076975dc609ebfb55..2d1738bd71c8adc639e7e53919f2cf988ea07ec3 100644 (file)
@@ -1,10 +1,14 @@
 #ifndef _PERF_UI_UTIL_H_
 #define _PERF_UI_UTIL_H_ 1
 
-#include <stdbool.h>
+#include <stdarg.h>
 
+int ui__getch(int delay_secs);
 int ui__popup_menu(int argc, char * const argv[]);
 int ui__help_window(const char *text);
-bool ui__dialog_yesno(const char *msg);
+int ui__dialog_yesno(const char *msg);
+int ui__question_window(const char *title, const char *text,
+                       const char *exit_msg, int delay_secs);
+int __ui__warning(const char *title, const char *format, va_list args);
 
 #endif /* _PERF_UI_UTIL_H_ */
index 8b2d37b59c9e2178c21256b240b3ca76b3081a76..3c6f7808efae53b84cab8926f87b3a5f37ea60ee 100644 (file)
@@ -162,19 +162,21 @@ void print_header(void)
 
 void dump_cnt(struct counters *cnt)
 {
-       fprintf(stderr, "package: %d ", cnt->pkg);
-       fprintf(stderr, "core:: %d ", cnt->core);
-       fprintf(stderr, "CPU: %d ", cnt->cpu);
-       fprintf(stderr, "TSC: %016llX\n", cnt->tsc);
-       fprintf(stderr, "c3: %016llX\n", cnt->c3);
-       fprintf(stderr, "c6: %016llX\n", cnt->c6);
-       fprintf(stderr, "c7: %016llX\n", cnt->c7);
-       fprintf(stderr, "aperf: %016llX\n", cnt->aperf);
-       fprintf(stderr, "pc2: %016llX\n", cnt->pc2);
-       fprintf(stderr, "pc3: %016llX\n", cnt->pc3);
-       fprintf(stderr, "pc6: %016llX\n", cnt->pc6);
-       fprintf(stderr, "pc7: %016llX\n", cnt->pc7);
-       fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, cnt->extra_msr);
+       if (!cnt)
+               return;
+       if (cnt->pkg) fprintf(stderr, "package: %d ", cnt->pkg);
+       if (cnt->core) fprintf(stderr, "core:: %d ", cnt->core);
+       if (cnt->cpu) fprintf(stderr, "CPU: %d ", cnt->cpu);
+       if (cnt->tsc) fprintf(stderr, "TSC: %016llX\n", cnt->tsc);
+       if (cnt->c3) fprintf(stderr, "c3: %016llX\n", cnt->c3);
+       if (cnt->c6) fprintf(stderr, "c6: %016llX\n", cnt->c6);
+       if (cnt->c7) fprintf(stderr, "c7: %016llX\n", cnt->c7);
+       if (cnt->aperf) fprintf(stderr, "aperf: %016llX\n", cnt->aperf);
+       if (cnt->pc2) fprintf(stderr, "pc2: %016llX\n", cnt->pc2);
+       if (cnt->pc3) fprintf(stderr, "pc3: %016llX\n", cnt->pc3);
+       if (cnt->pc6) fprintf(stderr, "pc6: %016llX\n", cnt->pc6);
+       if (cnt->pc7) fprintf(stderr, "pc7: %016llX\n", cnt->pc7);
+       if (cnt->extra_msr) fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, cnt->extra_msr);
 }
 
 void dump_list(struct counters *cnt)
index 8d02ccb10c598bc8c7a9e926e9b9500c75d51e37..8b4c2535b266a2abe17d3ad495b3a0fdfa8855a9 100755 (executable)
@@ -42,6 +42,7 @@ $default{"BISECT_MANUAL"}     = 0;
 $default{"BISECT_SKIP"}                = 1;
 $default{"SUCCESS_LINE"}       = "login:";
 $default{"DETECT_TRIPLE_FAULT"} = 1;
+$default{"NO_INSTALL"}         = 0;
 $default{"BOOTED_TIMEOUT"}     = 1;
 $default{"DIE_ON_FAILURE"}     = 1;
 $default{"SSH_EXEC"}           = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
@@ -84,6 +85,7 @@ my $grub_number;
 my $target;
 my $make;
 my $post_install;
+my $no_install;
 my $noclean;
 my $minconfig;
 my $start_minconfig;
@@ -115,6 +117,7 @@ my $timeout;
 my $booted_timeout;
 my $detect_triplefault;
 my $console;
+my $reboot_success_line;
 my $success_line;
 my $stop_after_success;
 my $stop_after_failure;
@@ -130,6 +133,12 @@ my %config_help;
 my %variable;
 my %force_config;
 
+# do not force reboots on config problems
+my $no_reboot = 1;
+
+# default variables that can be used
+chomp ($variable{"PWD"} = `pwd`);
+
 $config_help{"MACHINE"} = << "EOF"
  The machine hostname that you will test.
 EOF
@@ -241,6 +250,7 @@ sub read_yn {
 
 sub get_ktest_config {
     my ($config) = @_;
+    my $ans;
 
     return if (defined($opt{$config}));
 
@@ -254,16 +264,17 @@ sub get_ktest_config {
        if (defined($default{$config})) {
            print "\[$default{$config}\] ";
        }
-       $entered_configs{$config} = <STDIN>;
-       $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
-       if ($entered_configs{$config} =~ /^\s*$/) {
+       $ans = <STDIN>;
+       $ans =~ s/^\s*(.*\S)\s*$/$1/;
+       if ($ans =~ /^\s*$/) {
            if ($default{$config}) {
-               $entered_configs{$config} = $default{$config};
+               $ans = $default{$config};
            } else {
                print "Your answer can not be blank\n";
                next;
            }
        }
+       $entered_configs{$config} = process_variables($ans);
        last;
     }
 }
@@ -298,7 +309,7 @@ sub get_ktest_configs {
 }
 
 sub process_variables {
-    my ($value) = @_;
+    my ($value, $remove_undef) = @_;
     my $retval = "";
 
     # We want to check for '\', and it is just easier
@@ -316,6 +327,10 @@ sub process_variables {
        $retval = "$retval$begin";
        if (defined($variable{$var})) {
            $retval = "$retval$variable{$var}";
+       } elsif (defined($remove_undef) && $remove_undef) {
+           # for if statements, any variable that is not defined,
+           # we simple convert to 0
+           $retval = "${retval}0";
        } else {
            # put back the origin piece.
            $retval = "$retval\$\{$var\}";
@@ -331,10 +346,17 @@ sub process_variables {
 }
 
 sub set_value {
-    my ($lvalue, $rvalue) = @_;
+    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
 
     if (defined($opt{$lvalue})) {
-       die "Error: Option $lvalue defined more than once!\n";
+       if (!$override || defined(${$overrides}{$lvalue})) {
+           my $extra = "";
+           if ($override) {
+               $extra = "In the same override section!\n";
+           }
+           die "$name: $.: Option $lvalue defined more than once!\n$extra";
+       }
+       ${$overrides}{$lvalue} = $rvalue;
     }
     if ($rvalue =~ /^\s*$/) {
        delete $opt{$lvalue};
@@ -355,86 +377,274 @@ sub set_variable {
     }
 }
 
-sub read_config {
-    my ($config) = @_;
+sub process_compare {
+    my ($lval, $cmp, $rval) = @_;
+
+    # remove whitespace
+
+    $lval =~ s/^\s*//;
+    $lval =~ s/\s*$//;
+
+    $rval =~ s/^\s*//;
+    $rval =~ s/\s*$//;
+
+    if ($cmp eq "==") {
+       return $lval eq $rval;
+    } elsif ($cmp eq "!=") {
+       return $lval ne $rval;
+    }
+
+    my $statement = "$lval $cmp $rval";
+    my $ret = eval $statement;
+
+    # $@ stores error of eval
+    if ($@) {
+       return -1;
+    }
+
+    return $ret;
+}
+
+sub value_defined {
+    my ($val) = @_;
+
+    return defined($variable{$2}) ||
+       defined($opt{$2});
+}
+
+my $d = 0;
+sub process_expression {
+    my ($name, $val) = @_;
+
+    my $c = $d++;
+
+    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
+       my $express = $1;
+
+       if (process_expression($name, $express)) {
+           $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
+       } else {
+           $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
+       }
+    }
+
+    $d--;
+    my $OR = "\\|\\|";
+    my $AND = "\\&\\&";
+
+    while ($val =~ s/^(.*?)($OR|$AND)//) {
+       my $express = $1;
+       my $op = $2;
+
+       if (process_expression($name, $express)) {
+           if ($op eq "||") {
+               return 1;
+           }
+       } else {
+           if ($op eq "&&") {
+               return 0;
+           }
+       }
+    }
+
+    if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
+       my $ret = process_compare($1, $2, $3);
+       if ($ret < 0) {
+           die "$name: $.: Unable to process comparison\n";
+       }
+       return $ret;
+    }
+
+    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
+       if (defined $1) {
+           return !value_defined($2);
+       } else {
+           return value_defined($2);
+       }
+    }
+
+    if ($val =~ /^\s*0\s*$/) {
+       return 0;
+    } elsif ($val =~ /^\s*\d+\s*$/) {
+       return 1;
+    }
+
+    die ("$name: $.: Undefined content $val in if statement\n");
+}
+
+sub process_if {
+    my ($name, $value) = @_;
 
-    open(IN, $config) || die "can't read file $config";
+    # Convert variables and replace undefined ones with 0
+    my $val = process_variables($value, 1);
+    my $ret = process_expression $name, $val;
+
+    return $ret;
+}
+
+sub __read_config {
+    my ($config, $current_test_num) = @_;
+
+    my $in;
+    open($in, $config) || die "can't read file $config";
 
     my $name = $config;
     $name =~ s,.*/(.*),$1,;
 
-    my $test_num = 0;
+    my $test_num = $$current_test_num;
     my $default = 1;
     my $repeat = 1;
     my $num_tests_set = 0;
     my $skip = 0;
     my $rest;
+    my $line;
     my $test_case = 0;
+    my $if = 0;
+    my $if_set = 0;
+    my $override = 0;
 
-    while (<IN>) {
+    my %overrides;
+
+    while (<$in>) {
 
        # ignore blank lines and comments
        next if (/^\s*$/ || /\s*\#/);
 
-       if (/^\s*TEST_START(.*)/) {
+       if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
 
-           $rest = $1;
+           my $type = $1;
+           $rest = $2;
+           $line = $2;
 
-           if ($num_tests_set) {
-               die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
-           }
+           my $old_test_num;
+           my $old_repeat;
+           $override = 0;
+
+           if ($type eq "TEST_START") {
 
-           my $old_test_num = $test_num;
-           my $old_repeat = $repeat;
+               if ($num_tests_set) {
+                   die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
+               }
 
-           $test_num += $repeat;
-           $default = 0;
-           $repeat = 1;
+               $old_test_num = $test_num;
+               $old_repeat = $repeat;
 
-           if ($rest =~ /\s+SKIP(.*)/) {
-               $rest = $1;
+               $test_num += $repeat;
+               $default = 0;
+               $repeat = 1;
+           } else {
+               $default = 1;
+           }
+
+           # If SKIP is anywhere in the line, the command will be skipped
+           if ($rest =~ s/\s+SKIP\b//) {
                $skip = 1;
            } else {
                $test_case = 1;
                $skip = 0;
            }
 
-           if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
-               $repeat = $1;
-               $rest = $2;
-               $repeat_tests{"$test_num"} = $repeat;
+           if ($rest =~ s/\sELSE\b//) {
+               if (!$if) {
+                   die "$name: $.: ELSE found with out matching IF section\n$_";
+               }
+               $if = 0;
+
+               if ($if_set) {
+                   $skip = 1;
+               } else {
+                   $skip = 0;
+               }
            }
 
-           if ($rest =~ /\s+SKIP(.*)/) {
-               $rest = $1;
-               $skip = 1;
+           if ($rest =~ s/\sIF\s+(.*)//) {
+               if (process_if($name, $1)) {
+                   $if_set = 1;
+               } else {
+                   $skip = 1;
+               }
+               $if = 1;
+           } else {
+               $if = 0;
+               $if_set = 0;
            }
 
-           if ($rest !~ /^\s*$/) {
-               die "$name: $.: Gargbage found after TEST_START\n$_";
+           if (!$skip) {
+               if ($type eq "TEST_START") {
+                   if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
+                       $repeat = $1;
+                       $repeat_tests{"$test_num"} = $repeat;
+                   }
+               } elsif ($rest =~ s/\sOVERRIDE\b//) {
+                   # DEFAULT only
+                   $override = 1;
+                   # Clear previous overrides
+                   %overrides = ();
+               }
+           }
+
+           if (!$skip && $rest !~ /^\s*$/) {
+               die "$name: $.: Gargbage found after $type\n$_";
            }
 
-           if ($skip) {
+           if ($skip && $type eq "TEST_START") {
                $test_num = $old_test_num;
                $repeat = $old_repeat;
            }
 
-       } elsif (/^\s*DEFAULTS(.*)$/) {
-           $default = 1;
-
+       } elsif (/^\s*ELSE\b(.*)$/) {
+           if (!$if) {
+               die "$name: $.: ELSE found with out matching IF section\n$_";
+           }
            $rest = $1;
-
-           if ($rest =~ /\s+SKIP(.*)/) {
-               $rest = $1;
+           if ($if_set) {
                $skip = 1;
+               $rest = "";
            } else {
                $skip = 0;
+
+               if ($rest =~ /\sIF\s+(.*)/) {
+                   # May be a ELSE IF section.
+                   if (!process_if($name, $1)) {
+                       $skip = 1;
+                   }
+                   $rest = "";
+               } else {
+                   $if = 0;
+               }
            }
 
            if ($rest !~ /^\s*$/) {
                die "$name: $.: Gargbage found after DEFAULTS\n$_";
            }
 
+       } elsif (/^\s*INCLUDE\s+(\S+)/) {
+
+           next if ($skip);
+
+           if (!$default) {
+               die "$name: $.: INCLUDE can only be done in default sections\n$_";
+           }
+
+           my $file = process_variables($1);
+
+           if ($file !~ m,^/,) {
+               # check the path of the config file first
+               if ($config =~ m,(.*)/,) {
+                   if (-f "$1/$file") {
+                       $file = "$1/$file";
+                   }
+               }
+           }
+               
+           if ( ! -r $file ) {
+               die "$name: $.: Can't read file $file\n$_";
+           }
+
+           if (__read_config($file, \$test_num)) {
+               $test_case = 1;
+           }
+
        } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
 
            next if ($skip);
@@ -460,10 +670,10 @@ sub read_config {
            }
 
            if ($default || $lvalue =~ /\[\d+\]$/) {
-               set_value($lvalue, $rvalue);
+               set_value($lvalue, $rvalue, $override, \%overrides, $name);
            } else {
                my $val = "$lvalue\[$test_num\]";
-               set_value($val, $rvalue);
+               set_value($val, $rvalue, $override, \%overrides, $name);
 
                if ($repeat > 1) {
                    $repeats{$val} = $repeat;
@@ -490,13 +700,26 @@ sub read_config {
        }
     }
 
-    close(IN);
-
     if ($test_num) {
        $test_num += $repeat - 1;
        $opt{"NUM_TESTS"} = $test_num;
     }
 
+    close($in);
+
+    $$current_test_num = $test_num;
+
+    return $test_case;
+}
+
+sub read_config {
+    my ($config) = @_;
+
+    my $test_case;
+    my $test_num = 0;
+
+    $test_case = __read_config $config, \$test_num;
+
     # make sure we have all mandatory configs
     get_ktest_configs;
 
@@ -524,6 +747,18 @@ sub __eval_option {
     # Add space to evaluate the character before $
     $option = " $option";
     my $retval = "";
+    my $repeated = 0;
+    my $parent = 0;
+
+    foreach my $test (keys %repeat_tests) {
+       if ($i >= $test &&
+           $i < $test + $repeat_tests{$test}) {
+
+           $repeated = 1;
+           $parent = $test;
+           last;
+       }
+    }
 
     while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
        my $start = $1;
@@ -537,10 +772,14 @@ sub __eval_option {
        # otherwise see if the default OPT (without [$i]) exists.
 
        my $o = "$var\[$i\]";
+       my $parento = "$var\[$parent\]";
 
        if (defined($opt{$o})) {
            $o = $opt{$o};
            $retval = "$retval$o";
+       } elsif ($repeated && defined($opt{$parento})) {
+           $o = $opt{$parento};
+           $retval = "$retval$o";
        } elsif (defined($opt{$var})) {
            $o = $opt{$var};
            $retval = "$retval$o";
@@ -603,8 +842,20 @@ sub doprint {
 }
 
 sub run_command;
+sub start_monitor;
+sub end_monitor;
+sub wait_for_monitor;
 
 sub reboot {
+    my ($time) = @_;
+
+    if (defined($time)) {
+       start_monitor;
+       # flush out current monitor
+       # May contain the reboot success line
+       wait_for_monitor 1;
+    }
+
     # try to reboot normally
     if (run_command $reboot) {
        if (defined($powercycle_after_reboot)) {
@@ -615,12 +866,17 @@ sub reboot {
        # nope? power cycle it.
        run_command "$power_cycle";
     }
+
+    if (defined($time)) {
+       wait_for_monitor($time, $reboot_success_line);
+       end_monitor;
+    }
 }
 
 sub do_not_reboot {
     my $i = $iteration;
 
-    return $test_type eq "build" ||
+    return $test_type eq "build" || $no_reboot ||
        ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
        ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
 }
@@ -693,16 +949,29 @@ sub end_monitor {
 }
 
 sub wait_for_monitor {
-    my ($time) = @_;
+    my ($time, $stop) = @_;
+    my $full_line = "";
     my $line;
+    my $booted = 0;
 
     doprint "** Wait for monitor to settle down **\n";
 
     # read the monitor and wait for the system to calm down
-    do {
+    while (!$booted) {
        $line = wait_for_input($monitor_fp, $time);
-       print "$line" if (defined($line));
-    } while (defined($line));
+       last if (!defined($line));
+       print "$line";
+       $full_line .= $line;
+
+       if (defined($stop) && $full_line =~ /$stop/) {
+           doprint "wait for monitor detected $stop\n";
+           $booted = 1;
+       }
+
+       if ($line =~ /\n/) {
+           $full_line = "";
+       }
+    }
     print "** Monitor flushed **\n";
 }
 
@@ -719,10 +988,7 @@ sub fail {
        # no need to reboot for just building.
        if (!do_not_reboot) {
            doprint "REBOOTING\n";
-           reboot;
-           start_monitor;
-           wait_for_monitor $sleep_time;
-           end_monitor;
+           reboot $sleep_time;
        }
 
        my $name = "";
@@ -854,9 +1120,12 @@ sub get_grub_index {
     open(IN, "$ssh_grub |")
        or die "unable to get menu.lst";
 
+    my $found = 0;
+
     while (<IN>) {
        if (/^\s*title\s+$grub_menu\s*$/) {
            $grub_number++;
+           $found = 1;
            last;
        } elsif (/^\s*title\s/) {
            $grub_number++;
@@ -865,7 +1134,7 @@ sub get_grub_index {
     close(IN);
 
     die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
-       if ($grub_number < 0);
+       if (!$found);
     doprint "$grub_number\n";
 }
 
@@ -902,7 +1171,8 @@ sub wait_for_input
 
 sub reboot_to {
     if ($reboot_type eq "grub") {
-       run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'";
+       run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
+       reboot;
        return;
     }
 
@@ -1083,6 +1353,8 @@ sub do_post_install {
 
 sub install {
 
+    return if ($no_install);
+
     run_scp "$outputdir/$build_target", "$target_image" or
        dodie "failed to copy image";
 
@@ -1140,6 +1412,11 @@ sub get_version {
 }
 
 sub start_monitor_and_boot {
+    # Make sure the stable kernel has finished booting
+    start_monitor;
+    wait_for_monitor 5;
+    end_monitor;
+
     get_grub_index;
     get_version;
     install;
@@ -1250,6 +1527,10 @@ sub build {
 
     unlink $buildlog;
 
+    # Failed builds should not reboot the target
+    my $save_no_reboot = $no_reboot;
+    $no_reboot = 1;
+
     if (defined($pre_build)) {
        my $ret = run_command $pre_build;
        if (!$ret && defined($pre_build_die) &&
@@ -1272,15 +1553,15 @@ sub build {
        # allow for empty configs
        run_command "touch $output_config";
 
-       run_command "mv $output_config $outputdir/config_temp" or
-           dodie "moving .config";
+       if (!$noclean) {
+           run_command "mv $output_config $outputdir/config_temp" or
+               dodie "moving .config";
 
-       if (!$noclean && !run_command "$make mrproper") {
-           dodie "make mrproper";
-       }
+           run_command "$make mrproper" or dodie "make mrproper";
 
-       run_command "mv $outputdir/config_temp $output_config" or
-           dodie "moving config_temp";
+           run_command "mv $outputdir/config_temp $output_config" or
+               dodie "moving config_temp";
+       }
 
     } elsif (!$noclean) {
        unlink "$output_config";
@@ -1318,10 +1599,15 @@ sub build {
 
     if (!$build_ret) {
        # bisect may need this to pass
-       return 0 if ($in_bisect);
+       if ($in_bisect) {
+           $no_reboot = $save_no_reboot;
+           return 0;
+       }
        fail "failed build" and return 0;
     }
 
+    $no_reboot = $save_no_reboot;
+
     return 1;
 }
 
@@ -1356,10 +1642,7 @@ sub success {
 
     if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
        doprint "Reboot and wait $sleep_time seconds\n";
-       reboot;
-       start_monitor;
-       wait_for_monitor $sleep_time;
-       end_monitor;
+       reboot $sleep_time;
     }
 }
 
@@ -1500,10 +1783,7 @@ sub run_git_bisect {
 
 sub bisect_reboot {
     doprint "Reboot and sleep $bisect_sleep_time seconds\n";
-    reboot;
-    start_monitor;
-    wait_for_monitor $bisect_sleep_time;
-    end_monitor;
+    reboot $bisect_sleep_time;
 }
 
 # returns 1 on success, 0 on failure, -1 on skip
@@ -2066,10 +2346,7 @@ sub config_bisect {
 
 sub patchcheck_reboot {
     doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
-    reboot;
-    start_monitor;
-    wait_for_monitor $patchcheck_sleep_time;
-    end_monitor;
+    reboot $patchcheck_sleep_time;
 }
 
 sub patchcheck {
@@ -2178,12 +2455,31 @@ sub patchcheck {
 }
 
 my %depends;
+my %depcount;
 my $iflevel = 0;
 my @ifdeps;
 
 # prevent recursion
 my %read_kconfigs;
 
+sub add_dep {
+    # $config depends on $dep
+    my ($config, $dep) = @_;
+
+    if (defined($depends{$config})) {
+       $depends{$config} .= " " . $dep;
+    } else {
+       $depends{$config} = $dep;
+    }
+
+    # record the number of configs depending on $dep
+    if (defined $depcount{$dep}) {
+       $depcount{$dep}++;
+    } else {
+       $depcount{$dep} = 1;
+    } 
+}
+
 # taken from streamline_config.pl
 sub read_kconfig {
     my ($kconfig) = @_;
@@ -2230,30 +2526,19 @@ sub read_kconfig {
            $config = $2;
 
            for (my $i = 0; $i < $iflevel; $i++) {
-               if ($i) {
-                   $depends{$config} .= " " . $ifdeps[$i];
-               } else {
-                   $depends{$config} = $ifdeps[$i];
-               }
-               $state = "DEP";
+               add_dep $config, $ifdeps[$i];
            }
 
        # collect the depends for the config
        } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
 
-           if (defined($depends{$1})) {
-               $depends{$config} .= " " . $1;
-           } else {
-               $depends{$config} = $1;
-           }
+           add_dep $config, $1;
 
        # Get the configs that select this config
-       } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
-           if (defined($depends{$1})) {
-               $depends{$1} .= " " . $config;
-           } else {
-               $depends{$1} = $config;
-           }
+       } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
+
+           # selected by depends on config
+           add_dep $1, $config;
 
        # Check for if statements
        } elsif (/^if\s+(.*\S)\s*$/) {
@@ -2365,11 +2650,18 @@ sub make_new_config {
     close OUT;
 }
 
+sub chomp_config {
+    my ($config) = @_;
+
+    $config =~ s/CONFIG_//;
+
+    return $config;
+}
+
 sub get_depends {
     my ($dep) = @_;
 
-    my $kconfig = $dep;
-    $kconfig =~ s/CONFIG_//;
+    my $kconfig = chomp_config $dep;
 
     $dep = $depends{"$kconfig"};
 
@@ -2419,8 +2711,7 @@ sub test_this_config {
        return undef;
     }
 
-    my $kconfig = $config;
-    $kconfig =~ s/CONFIG_//;
+    my $kconfig = chomp_config $config;
 
     # Test dependencies first
     if (defined($depends{"$kconfig"})) {
@@ -2510,6 +2801,14 @@ sub make_min_config {
 
     my @config_keys = keys %min_configs;
 
+    # All configs need a depcount
+    foreach my $config (@config_keys) {
+       my $kconfig = chomp_config $config;
+       if (!defined $depcount{$kconfig}) {
+               $depcount{$kconfig} = 0;
+       }
+    }
+
     # Remove anything that was set by the make allnoconfig
     # we shouldn't need them as they get set for us anyway.
     foreach my $config (@config_keys) {
@@ -2548,8 +2847,13 @@ sub make_min_config {
        # Now disable each config one by one and do a make oldconfig
        # till we find a config that changes our list.
 
-       # Put configs that did not modify the config at the end.
        my @test_configs = keys %min_configs;
+
+       # Sort keys by who is most dependent on
+       @test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
+                         @test_configs ;
+
+       # Put configs that did not modify the config at the end.
        my $reset = 1;
        for (my $i = 0; $i < $#test_configs; $i++) {
            if (!defined($nochange_config{$test_configs[0]})) {
@@ -2659,10 +2963,7 @@ sub make_min_config {
        }
 
        doprint "Reboot and wait $sleep_time seconds\n";
-       reboot;
-       start_monitor;
-       wait_for_monitor $sleep_time;
-       end_monitor;
+       reboot $sleep_time;
     }
 
     success $i;
@@ -2783,6 +3084,9 @@ sub set_test_option {
 # First we need to do is the builds
 for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
+    # Do not reboot on failing test options
+    $no_reboot = 1;
+
     $iteration = $i;
 
     my $makecmd = set_test_option("MAKE_CMD", $i);
@@ -2811,6 +3115,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $reboot_type = set_test_option("REBOOT_TYPE", $i);
     $grub_menu = set_test_option("GRUB_MENU", $i);
     $post_install = set_test_option("POST_INSTALL", $i);
+    $no_install = set_test_option("NO_INSTALL", $i);
     $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
     $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
     $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
@@ -2832,6 +3137,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $console = set_test_option("CONSOLE", $i);
     $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
     $success_line = set_test_option("SUCCESS_LINE", $i);
+    $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
     $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
     $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
     $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
@@ -2850,9 +3156,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
     chdir $builddir || die "can't change directory to $builddir";
 
-    if (!-d $tmpdir) {
-       mkpath($tmpdir) or
-           die "can't create $tmpdir";
+    foreach my $dir ($tmpdir, $outputdir) {
+       if (!-d $dir) {
+           mkpath($dir) or
+               die "can't create $dir";
+       }
     }
 
     $ENV{"SSH_USER"} = $ssh_user;
@@ -2889,8 +3197,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
        $run_type = "ERROR";
     }
 
+    my $installme = "";
+    $installme = " no_install" if ($no_install);
+
     doprint "\n\n";
-    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
+    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
 
     unlink $dmesg;
     unlink $buildlog;
@@ -2911,6 +3222,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
            die "failed to checkout $checkout";
     }
 
+    $no_reboot = 0;
+
+
     if ($test_type eq "bisect") {
        bisect $i;
        next;
@@ -2929,6 +3243,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
        build $build_type or next;
     }
 
+    if ($test_type eq "install") {
+       get_version;
+       install;
+       success $i;
+       next;
+    }
+
     if ($test_type ne "build") {
        my $failed = 0;
        start_monitor_and_boot or $failed = 1;
index b8bcd14b5a4da7f3e2979b75118196971acda3e2..dbedfa196727ddc01ff0b5f563d0ce08dfeb9e95 100644 (file)
 # the same option name under the same test or as default
 # ktest will fail to execute, and no tests will run.
 #
+# DEFAULTS OVERRIDE
+#
+# Options defined in the DEFAULTS section can not be duplicated
+# even if they are defined in two different DEFAULT sections.
+# This is done to catch mistakes where an option is added but
+# the previous option was forgotten about and not commented.
+#
+# The OVERRIDE keyword can be added to a section to allow this
+# section to override other DEFAULT sections values that have
+# been defined previously. It will only override options that
+# have been defined before its use. Options defined later
+# in a non override section will still error. The same option
+# can not be defined in the same section even if that section
+# is marked OVERRIDE.
+#
+#
+#
+# Both TEST_START and DEFAULTS sections can also have the IF keyword
+# The value after the IF must evaluate into a 0 or non 0 positive
+# integer, and can use the config variables (explained below).
+#
+# DEFAULTS IF ${IS_X86_32}
+#
+# The above will process the DEFAULTS section if the config
+# variable IS_X86_32 evaluates to a non zero positive integer
+# otherwise if it evaluates to zero, it will act the same
+# as if the SKIP keyword was used.
+#
+# The ELSE keyword can be used directly after a section with
+# a IF statement.
+#
+# TEST_START IF ${RUN_NET_TESTS}
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
+#
+# ELSE
+#
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-normal
+#
+#
+# The ELSE keyword can also contain an IF statement to allow multiple
+# if then else sections. But all the sections must be either
+# DEFAULT or TEST_START, they can not be a mixture.
+#
+# TEST_START IF ${RUN_NET_TESTS}
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
+#
+# ELSE IF ${RUN_DISK_TESTS}
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-tests
+#
+# ELSE IF ${RUN_CPU_TESTS}
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-cpu
+#
+# ELSE
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
+#
+# The if statement may also have comparisons that will and for
+# == and !=, strings may be used for both sides.
+#
+# BOX_TYPE := x86_32
+#
+# DEFAULTS IF ${BOX_TYPE} == x86_32
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-32
+# ELSE
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-64
+#
+# The DEFINED keyword can be used by the IF statements too.
+# It returns true if the given config variable or option has been defined
+# or false otherwise.
+#
+# 
+# DEFAULTS IF DEFINED USE_CC
+# CC := ${USE_CC}
+# ELSE
+# CC := gcc
+#
+#
+# As well as NOT DEFINED.
+#
+# DEFAULTS IF NOT DEFINED MAKE_CMD
+# MAKE_CMD := make ARCH=x86
+#
+#
+# And/or ops (&&,||) may also be used to make complex conditionals.
+#
+# TEST_START IF (DEFINED ALL_TESTS || ${MYTEST} == boottest) && ${MACHINE} == gandalf
+#
+# Notice the use of paranthesis. Without any paranthesis the above would be
+# processed the same as:
+#
+# TEST_START IF DEFINED ALL_TESTS || (${MYTEST} == boottest && ${MACHINE} == gandalf)
+#
+#
+#
+# INCLUDE file
+#
+# The INCLUDE keyword may be used in DEFAULT sections. This will
+# read another config file and process that file as well. The included
+# file can include other files, add new test cases or default
+# statements. Config variables will be passed to these files and changes
+# to config variables will be seen by top level config files. Including
+# a file is processed just like the contents of the file was cut and pasted
+# into the top level file, except, that include files that end with
+# TEST_START sections will have that section ended at the end of
+# the include file. That is, an included file is included followed
+# by another DEFAULT keyword.
+#
+# Unlike other files referenced in this config, the file path does not need
+# to be absolute. If the file does not start with '/', then the directory
+# that the current config file was located in is used. If no config by the
+# given name is found there, then the current directory is searched.
+#
+# INCLUDE myfile
+# DEFAULT
+#
+# is the same as:
+#
+# INCLUDE myfile
+#
+# Note, if the include file does not contain a full path, the file is
+# searched first by the location of the original include file, and then
+# by the location that ktest.pl was executed in.
+#
 
 #### Config variables ####
 #
 
 # The default test type (default test)
 # The test types may be:
-#   build - only build the kernel, do nothing else
-#   boot - build and boot the kernel
-#   test - build, boot and if TEST is set, run the test script
+#   build   - only build the kernel, do nothing else
+#   install - build and install, but do nothing else (does not reboot)
+#   boot    - build, install, and boot the kernel
+#   test    - build, boot and if TEST is set, run the test script
 #          (If TEST is not set, it defaults back to boot)
 #   bisect - Perform a bisect on the kernel (see BISECT_TYPE below)
 #   patchcheck - Do a test on a series of commits in git (see PATCHCHECK below)
 # or on some systems:
 #POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
 
+# If for some reason you just want to boot the kernel and you do not
+# want the test to install anything new. For example, you may just want
+# to boot test the same kernel over and over and do not want to go through
+# the hassle of installing anything, you can set this option to 1
+# (default 0)
+#NO_INSTALL = 1
+
 # If there is a script that you require to run before the build is done
 # you can specify it with PRE_BUILD.
 #
 # (default "login:")
 #SUCCESS_LINE = login:
 
+# To speed up between reboots, defining a line that the
+# default kernel produces that represents that the default
+# kernel has successfully booted and can be used to pass
+# a new test kernel to it. Otherwise ktest.pl will wait till
+# SLEEP_TIME to continue.
+# (default undefined)
+#REBOOT_SUCCESS_LINE = login:
+
 # In case the console constantly fills the screen, having
 # a specified time to stop the test after success is recommended.
 # (in seconds)
 # another test. If a reboot to the reliable kernel happens,
 # we wait SLEEP_TIME for the console to stop producing output
 # before starting the next test.
+#
+# You can speed up reboot times even more by setting REBOOT_SUCCESS_LINE.
 # (default 60)
 #SLEEP_TIME = 60